Giter VIP home page Giter VIP logo

redux-mock-store's Introduction

redux-mock-store Circle CI

npm

A mock store for testing Redux async action creators and middleware. The mock store will create an array of dispatched actions which serve as an action log for tests.

Please note that this library is designed to test the action-related logic, not the reducer-related one. In other words, it does not update the Redux store. If you want a complex test combining actions and reducers together, take a look at other libraries (e.g., redux-actions-assertions). Refer to issue #71 for more details.

Install

npm install redux-mock-store --save-dev

Or

yarn add redux-mock-store --dev

Usage

Synchronous actions

The simplest usecase is for synchronous actions. In this example, we will test if the addTodo action returns the right payload. redux-mock-store saves all the dispatched actions inside the store instance. You can get all the actions by calling store.getActions(). Finally, you can use any assertion library to test the payload.

import configureStore from 'redux-mock-store' //ES6 modules
const { configureStore } = require('redux-mock-store') //CommonJS

const middlewares = []
const mockStore = configureStore(middlewares)

// You would import the action from your codebase in a real scenario
const addTodo = () => ({ type: 'ADD_TODO' })

it('should dispatch action', () => {

  // Initialize mockstore with empty state
  const initialState = {}
  const store = mockStore(initialState)

  // Dispatch the action
  store.dispatch(addTodo())

  // Test if your store dispatched the expected actions
  const actions = store.getActions()
  const expectedPayload = { type: 'ADD_TODO' }
  expect(actions).toEqual([expectedPayload])
})

Asynchronous actions

A common usecase for an asynchronous action is a HTTP request to a server. In order to test those types of actions, you will need to call store.getActions() at the end of the request.

import configureStore from 'redux-mock-store'
import thunk from 'redux-thunk'

const middlewares = [thunk] // add your middlewares like `redux-thunk`
const mockStore = configureStore(middlewares)

// You would import the action from your codebase in a real scenario
function success() {
  return {
    type: 'FETCH_DATA_SUCCESS'
  }
}

function fetchData () {
  return dispatch => {
    return fetch('/users.json') // Some async action with promise
      .then(() => dispatch(success()))
  };
}

it('should execute fetch data', () => {
  const store = mockStore({})

  // Return the promise
  return store.dispatch(fetchData())
    .then(() => {
      const actions = store.getActions()
      expect(actions[0]).toEqual(success())
    })
})

API

configureStore(middlewares?: Array) => mockStore: Function

Configure mock store by applying the middlewares.

mockStore(getState?: Object,Function) => store: Function

Returns an instance of the configured mock store. If you want to reset your store after every test, you should call this function.

store.dispatch(action) => action

Dispatches an action through the mock store. The action will be stored in an array inside the instance and executed.

store.getState() => state: Object

Returns the state of the mock store.

store.getActions() => actions: Array

Returns the actions of the mock store.

store.clearActions()

Clears the stored actions.

store.subscribe(callback: Function) => unsubscribe: Function

Subscribe to the store.

store.replaceReducer(nextReducer: Function)

Follows the Redux API.

Old version (< 1.x.x)

https://github.com/arnaudbenard/redux-mock-store/blob/v0.0.6/README.md

Versions

The following versions are exposed by redux-mock-store from the package.json:

  • main: commonJS Version
  • module/js:next: ES Module Version
  • browser : UMD version

License

The MIT License

redux-mock-store's People

Contributors

arnaudbenard avatar arturszott avatar asgarddesigns avatar brauliodiez avatar butlersrepos avatar bvaughn avatar cesarp avatar chrisblossom avatar davidlgj avatar dipnlik avatar dmitry-zaets avatar dylanparry avatar haroenv avatar itsjw avatar jacobrask avatar jtfell avatar laurens avatar lukeapage avatar mayank23 avatar mchao409 avatar mdarse avatar newyork-anthonyng avatar ohtangza avatar sbason avatar subblue avatar therewillbecode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redux-mock-store's Issues

Action dispatched in catch statements don't get called.

I created this Stackoverflow questions a few days ago, but I didn't get an answer. I tried since but I didn't find a solution to the problem.

The problem basically occurs when I dispatch actions in catch statements. They neither show up in store.getActions() nor is the state altert. I described it in relative detail in the question so I won't repeat it here. Feel free to request more info though.

I'm still not sure if it's a bug or if I'm just doing it wrong.

redux-thunk "actions may not have undefined type property"

Since upgrading to 1.1.0 or above (previously on 1.0.4), using redux-thunk, dispatching a thunk fails with "Actions may not have an undefined "type" property. Have you misspelled a constant?" (this was introduced in 2f7fa44).

For example, my action creator returns a thunk:

export function fetchSomething(smthg) {
  return dispatch => {
    return API.someCall(smthg).then(things => {
      dispatch(plainActionCreator(things));
      return things;
    });
  };
}

As well, I've configured the mock store to use redux-thunk.

My tests simply dispatch this action using a mock store:

describe('Blah', () => {
    it('should work', () => {
       return store.dispatch(fetchSomething('code'));
   });
});

Add fake subscribe method

Is it an idea to add a fake subscribe method so that you can use the store to test react-redux connectors? It doesn't even have to do anything by itself, you might be allowed to pass in your own spy or fake method.

Error : Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.

I'm using Jest to do unit test based on Jasmine 2
When I was testing my async action store having Parse query
It throws this error :
''Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVL."

Here is my code from _tests/actions/auth-test.js

it('should creates SIGNUP_REQUEST and SIGNUP_SUCCESS when signup has been done successfully', (done) => {

        /* If this account has already exists in Parse database, it will get SIGNUP_ERROR */

        const expectedActions = [
            { type: 'SIGNUP_REQUEST', payload: { username, password } },
            { type: 'SIGNUP_SUCCESS', payload: { user: { /* whatever. Anyway, it needs to be defined */ } } },
        ];

        const store = mockStore({}, expectedActions, done);

        store.dispatch(Auth.signup(username, password));
    })

Finally, I revised some code from yours and tested successfully.
It seems that the main problem is Jasmine done() doesn't be invoked, so it causes this error.

Here is my revised code :

function configureMockStore(middlewares = []) {

    return function mockStore(getState, expectedActions, done) {

        if (!Array.isArray(expectedActions)) {
            throw new Error('expectedActions should be an array of expected actions.');
        }

        if (typeof done !== 'undefined' && typeof done !== 'function') {
            throw new Error('done should either be undefined or function.');
        }

        function mockStoreWithoutMiddleware() {
            return {
                getState() {
                    return typeof getState === 'function' ? getState() : getState;
                },

                dispatch(action) {

                    const expectedAction = expectedActions.shift();

                    /* Customize for auth action test */
                    switch(action.type) {

                    case 'SIGNUP_REQUEST':
                    case 'LOGIN_REQUEST':
                        expect(action).toEqual(expectedAction);
                        break;
                    case 'SIGNUP_SUCCESS':
                    case 'LOGIN_SUCCESS':
                        expect(action.type).toEqual(expectedAction.type);
                        expect(action.payload.user).toBeDefined();
                        break;
                    case 'SIGNUP_ERROR':
                    case 'LOGIN_ERROR':
                        expect(action.type).toEqual(expectedAction.type);
                        expect(action.payload.error).toBeDefined();
                        break;
                    }

                    if (done && !expectedActions.length) {
                        done();
                    }

                    return action;
                }
            }
        }

        const mockStoreWithMiddleware = applyMiddleware(
            ...middlewares
        )(mockStoreWithoutMiddleware);

        return mockStoreWithMiddleware();
    }
}

Showing where the error is with the expected actions assertion

Firstly this library is proving to be very useful when testing my app, so many thanks!

One thing I have found is that if there is a mismatch with the expected actions in my test and the actual code then it can be tricky to find exactly where the problem is - typically the mocha test just times out because the done callback hasn't been triggered.

Is there a way to log the difference between expected and actual actions called?

Async dispatch calls after an error fails

I have an asynchronous callback calling dispatch. When the previous dispatch fails, the second one is called again and the test fails with Error: done() called multiple times. v0.0.4 fixes this with #5 but v0.0.6 breaks it with #7

Second expected action was ignored

Action creators:

export function sendVerCode(mobile) {
      return dispatch => {
        dispatch(requestSendCode(mobile))
        return fetch('/api/signup-send-code', 
                      {
                        method: 'post',                      
                        body: `mobile=${mobile}`
                      }
          ).then(response => response.json())
           .then(json => {
              if(json.success) {
                dispatch(sendCodeSucceed(json))
              } else {
                dispatch(sendCodeFailed(json))
              }

            })
           .catch((err) => dispatch(sendCodeFailed('send verfiy code failed',err)) )
      }
  }

  function requestSendCode(mobile) {
    return {
      type: REQUEST_SEND_CODE,
      mobile:mobile,
      requestedAt:Date.now()
    }
  }

  function sendCodeSucceed(json) {
    return {
      type: SEND_CODE_SUCCEED,
      result: json,
      receivedAt: Date.now()
    }
  }

  function sendCodeFailed(message,err) {
    return {
      type: SEND_CODE_FAILED,
      message: message,
      err:err,
      receivedAt: Date.now()
    }
  }

Tests:

it.only('creates SEND_CODE_SUCCEED when sendVerCode has been done', () => {
      fetchMock.mock({
              routes: {
                name: 'route',
                matcher: '/api/signup-send-code',
                method: 'POST',
                response: { success: true }
              }
            })

        var expectedActions = [
          { type: REQUEST_SEND_CODE, mobile:'13911088888',requestedAt:Date.now()},
          { type: SEND_CODE_FAILED, result:{ success: true } } //Here should be SEND_CODE_SUCCEED
        ]
        var store = mockStore(Map({}), expectedActions)
        store.dispatch(sendVerCode('13911088888'))
     })

Second action should be SEND_CODE_SUCCEED,But the test passed!It seems the second expected action was ignored.

store.subscribe

Would it be helpful to add store.subscribe method?

I'm just getting started learning how to test react, so I'm not sure what it'd look like. I may be understanding this as intended to use for a completely different purpose than I'm trying to test.

I'm trying to do this:

// I have a shallowRender helper util
const component = shallowRender(
        <Provider store={store}>
          <ConnectedCounterContainer />
        </Provider>
      )

so I can simply test to see if the component received the prop count: 0

but I get:

Warning: Failed Context Types: Required child context `store.subscribe` was not specified in `Provider`.

so I'm assuming it wants a store.subscribe() method on the mocked store.

What's the suggested way to test action creators that rely on previous dispatch calls?

We've an action creator that looks something like this:

export function changeFilter(from, to) {
  return (dispatch, getState) => {
    // Updates the state with the new values and sets a loading flag
    dispatch(changeFilterRequest(from, to));

    // Now I want to use those newly-set values to build a query string
    // However, the stubbed implementation of `dispatch` doesn't use reducers,
    // so `getState` returns the original value!
    const { activeUsers } = getState();
    return doSomeWebRequest(activeUsersParams(activeUsers))
      .then(response => dispatch(changeFilterSuccess(response)))
  };
}

Like many asynchronous action creators, we split it up into two actions, one to signal the start of an action and another to signal the end. However, our web request in the middle relies on the values set by the first dispatch.

The implementation of dispatch is pretty sparse, and in (obvious) hindsight, we never pass the reducers to the mocked store!

Are there any existing patterns for performing these types of tests?

Thanks for a great library; keep up the good work!

An option to only compare the provided properties in expectedActions

I have an action creator which which updates a user, and then dispatches another action to display a notification. The notification displays for a few seconds and then disappears. To make this happen a private id is assigned to the action by the notification action creator.

In my test, I'd like to ensure that both the user update action and the notification action are triggered successfully.

In expectedActions I can add a notification action with the correct action type, with the message in the payload, but I can't provide the private notification id. Because the action I provided doesn't match exactly (the provided action has no id), the test fails.

Ideally I'd like an option to make the equality test less strict, one that ensures that the all the properties of the object in expectedActions are present and equal in the actual action, and that any additional properties in the actual action are ignored.

So for the purpose of my test, I'd like the following to be considered equal:

Object in expectedActions:
{ type: types.NOTIFICATION, message: 'user updated' }

Actual action:
{ type: types.NOTIFICATION, id: 616, message: 'user updated' ...any other properties }

I can understand if this goes against the spirit of the project, in which case I'd certainly appreciate any suggestions on how to handle my situation.

Thanks.

store.getActions() return array with actions but sinon spy(store,'dispatch') callCount return 0 store does not change state

   TestUtils.Simulate.click(btnNext)
    console.log(store.dispatch.callCount) //0
    TestUtils.Simulate.click(btnNext)
    console.log(store.dispatch.callCount) //0
    console.log(store.getActions()) //[ { type: 'CHANGE_BLOCK_LAYOUT',
                                                         //blockId: '2c7dbb58-2025-4b9f-b8ad-c206ed5f15a0',
                                                        //layout: 1 },
                                                        // { type: 'CHANGE_BLOCK_LAYOUT',
                                                        // blockId: '2c7dbb58-2025-4b9f-b8ad-c206ed5f15a0',
                                                          //layout: 1 } ]

How to apply reducer to the store(Use replaceReducer(nextReducer:Function) ?), to monitor the incoming action?

I am testing actions in redux, but there is asyn behavior in the middleware. So, I don't to want to monitor the action when I invoke dispatch(), whate I really want is to monitor the incoming actions in the reducer. is there any way to make it (method replaceReducer seems doesn't work well)? Thanks a lot!

I found the monitor method dispatch() is ok for my question, but i can only get the first action, and can't catch the second ation. setTimeout() don't work well.

Tests not failing when expectations are not met

If I set up a test that should fail because the dispatched actions do not meet the expectations, the test is in-fact passing which can be quite dangerous.

This is using redux-mock-store 0.0.6 and Jest 0.8.2.

I believe the problem lies here:

} catch (e) {
  if (done) {
    done(e);
  }
  throw e;
}

I was able to cause the test to fail as expected by simply not calling done, e.g:

} catch (e) {
  if (done) {
    //done(e);
  }
  throw e;
}

I'm not 100% sure if this is an issue with this library or one with Jest, therefore I have not put together a PR yet until the matter has been discussed.

UnhandledPromiseRejectionWarning: Unhandled promise rejection: TypeError: dispatch is not a function

My mocha tests are passing, but I am getting this new error about how 'dispatch' is not a function.

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
const mockStore = configureMockStore([thunk]);

it('should attempt to login', (done) => {
    const userInfo = {email: 'Fizz', password: 'Buzz'};
    const userActions = require('../../../src/actions/userActions');
    const store = mockStore({});
    const dispatch = store.dispatch;
    const login = userActions.login;

    store.subscribe(() => {
        expect(store.getActions()[0].type).to.equal('LOG_IN');
        expect(store.getActions()[0].data.email).to.equal('Fizz');
        expect(store.getActions()[0].data.password).to.equal('Buzz');
        done();
    });

    dispatch(userActions.asyncLogin(userInfo)(dispatch(login(userInfo))));
});

How can I import my reducers to mockStore

describe('fetchArticleList action', () => {
    it('Get articles should sucess with correctly api', () => {
        const store = mockStore({})
        function fetchArticleListSuccess(json) {
          return {
            type: 'FETCH_ARTICLE_LIST_SUCCESS',
            ArticleList: json
          }
        }
        return store.dispatch(fetchArticleList(ARTICLES_API))
            .then(() => {
                               //the json have a lot of strings
                expect(store.getActions()[1]).toEqual(fetchArticleListSuccess())
                console.log(store.getState()) // => {}
            })
    })
})

so I wonder 'const store = mockStore({})' or 'const mockStore = configureStore(meddlewares)'
could applying my reducers in the mock Store
but I don't how to write the code

Callback called multiple times

Hello! I have an issue with failing tests on Mocha.

Given an array of expected actions, if the last one fails Mocha return me the correct wrong expectation, but if another actions fails (before the last), the callback is called multiple times and Mocha return me thi exception: Error: done() called multiple times. So I don't know which action failed!

The problem is that the mocked store when catching an exception, pass it as argument to the callback and doesn't throw it, so it keeps running and when it reach the last action, calls the callback again.

I don't know if that's a problem only with Mocha though, in that case maybe it should be configurable to make it work with every testing library.

Here's a simple test to replicate the behaviour:

  it('handles multiple actions', done => {
    const store = mockStore({}, [{ type: 'ADD_ITEM' }, { type: 'REMOVE_ITEM' }], done);

    store.dispatch({ type: 'ADD_ITEMS' });
    store.dispatch({ type: 'REMOVE_ITEM' });
  });

Mock Store State is not being updated after an action has been dispatched

Hello,

For some reason the state within my mocked store is not being updated after an action has been dispatched. I've pasted my unit test below. Any suggestion on how to proceed would be greatly appreciated.

describe('Landing Page Action Creators', () => {
    let store = mockStore({app: {kbbToken: 'MTI2MDk2NjUy'}, ymmt: YMMT_INITIAL_STATE});

    beforeEach(() => {
        // Redux Mock store - clear actions before each test to assert the new actions being dispatched
        store.clearActions();
    });


    describe('Years', () => {
        // getYears()
        it('getYears() -> Should return an array of years dating back to 1992', (done) => {

            const expectedActions = [
                {type: 'GET_YEARS_PENDING'},
                {type: 'GET_YEARS_FULFILLED', payload: LandingMockedResponses.getYears}
            ];

            return store.dispatch(LandingActions.fetchYears())
                .then(() => { // return of async actions
                    done();
                    expect(store.getActions()).to.eql(expectedActions)
                })
        });
        // ***END getYears()

        // setYear(2016)
        it('setYear(year) -> Set selected year (ymmt)', (done) => {
            let expectedActions = [
                {type: 'SET_YEAR', payload: 2016},
                { type: 'GET_MAKES_PENDING' }
            ];
            store.dispatch(LandingActions.setYear(2016));
            done();

            expect(store.getActions()).to.eql(expectedActions);
        });
        // ***END setYear(2016)
    });

    describe('Makes', () => {
        // getMakes()
        it('getMakes() -> Should return an array of makes based on the year passed in', (done) => {
            store.clearActions();

            console.log(store.getState().ymmt);

            let expectedActions = [
                {type: 'GET_MAKES_PENDING'},
                {type: 'GET_MAKES_FULFILLED', payload: LandingMockedResponses.getMakes}
            ];

            return store.dispatch(LandingActions.fetchMakes(2016))
                .then(() => { // return of async actions
                    done();
                    expect(store.getActions()).to.eql(expectedActions)
                })
        });
        // ***END getMakes()
    });



});

Timeout error: `No match for request`

I'm a novice so this may be a trivial question.

I'm currently trying to test my actions for signing up a user. For some reason my post request fails by timing out, when my endpoints seem to be fine.

// the test
it('creates SIGNUP_USER_SUCCESS when user completes signup', (done) => {

    var signupUser = require('../actions/auth/signup').signupUser;

    nock('http://api.dockerhost')
        .post('/signup', {
            first_name: 'Robin',
            last_name: 'Kim',
            username: '[email protected]',
            password: 'password'
        })
        .reply(200, {
            body: {
                user: {
                    username: '[email protected]'
                }
            }
        })

    const expectedActions = [
        { type: constants.SIGNUP_USER_REQUEST },
        { type: constants.SIGNUP_USER_SUCCESS }
    ];

    const store = mockStore({ user: {}}, expectedActions, done);
    store.dispatch(signupUser('Robin Kim', '[email protected]', 'password'));
})

// the action
const signupUser = (name, username, password) => {

    const first_name = name.split(' ').slice(0, -1).join(' ');
    const last_name = name.split(' ').slice(-1).join(' ');
    const url = `http://api.dockerhost/signup`;
    const data = { first_name, last_name, username, password }

    return (dispatch) => {
        dispatch(signupUserRequest());
        return request
          .post(url)
          .type('form')
          .send(data)
          .end()
          .then((response) => {
            console.log('the response', response)
            dispatch(signupUserSuccess());
            return dispatch(loginUser(username, password, '/downloads'));
          })
          .catch((error) => {
            console.log('error', error) // this is where I get the error
            return dispatch(signupUserFailure({
                response: {
                    statusText: error.response.body.errors.username.message,
                    field: error.response.body.errors.username.path
                }
            }))
          })
    }
}

// the error response
`{ [Error: Nock: No match for request POST http://api.dockerhost/signup first_name=Robin&last_name=Kim&username=rokim8%40gmail.com&password=password] status: 404, statusCode: 404, response: undefined }`

// the test log
`Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.`

It seems like it simply cannot hit my /signup endpoint, but I'm unsure as to why.

Test passes even if not all expected actions are dispatched

I have the following set-up
actions.js

export function loadData() {
    return function (dispatch) {
        dispatch(transactions([876]));
    };
}

actions-test.js

  jest.dontMock('../actions');
  jest.dontMock('redux-mock-store');
  jest.dontMock('redux-thunk');

  const configureMockStore = require('redux-mock-store');
  const thunk = require('redux-thunk');
  const middlewares = [ thunk ];
  const mockStore = configureMockStore(middlewares);

describe('actions', () => {    
  it('should load data', (done) => {
    const expectedActions = [
      { type: actions.TRANSACTIONS, transactions : [876] },
      //{ type: actions.DOES_NOT_EXIST, foo : [] },
      //{ type: actions.EXISTS, foo : [] }
    ];

    const store = mockStore({}, expectedActions, done);
    store.dispatch(actions.loadData());
  });
});

Running the above test passes as expected.

The problem is if I uncomment

      //{ type: actions.DOES_NOT_EXIST, foo : [] },
      //{ type: actions.EXISTS, foo : [] }

the test still passes even though now only one of the 3 expectedActions is dispatched.

Is this a bug, or am I misunderstanding something?

getActions() returns undefined which results in TypeError

Here's my test:

  it('should save entry', () => {
    const expectedActions = [
      {type: ENTRY_SAVE_REQUEST},
      {type: ENTRY_SAVE_SUCCESS},
      {type: SYNC_STARTED},
    ];

    // const store = mockStore({}, expectedActions)
    // return store.dispatch(actions.saveEntry())
    const store = mockStore({})
    store.dispatch(actions.saveEntry())
    let retActions = store.getActions()
    expect(retActions).toEqual(expectedActions) // exception thrown here
  })

Also tried the old syntax (commented out) but it passes every time, no matter if expected actions are correct or not.

Packages I'm using:

The full error:

  - Cannot read property 'toObject' of undefined }) ] to equal [ Object({ type: 'ENTRY_SAVE_REQUEST' }), Object({ type: 'ENTRY_SAVE_SUCCESS' }), Object({ type: 'SYNC_STARTED' }) ].
        at jasmine.buildExpectationResult (node_modules/jest-jasmine2/src/index.js:80:44)
        at Object.eval (src/reducers/entry/__tests__/entryActions-test.js:86:20)
        at Object.<anonymous> (node_modules/jest-jasmine2/src/jasmine-pit.js:35:32)
        at Object.<anonymous> (node_modules/jest-jasmine2/src/jasmine-pit.js:40:11)
        at Object.<anonymous> (node_modules/jest-jasmine2/src/jasmine-pit.js:40:11)
        at Object.<anonymous> (node_modules/jest-jasmine2/src/jasmine-pit.js:40:11)
        at jasmine2 (node_modules/jest-jasmine2/src/index.js:253:7)
        at Test.run (node_modules/jest-cli/src/Test.js:44:12)
        at handle (node_modules/worker-farm/lib/child/index.js:41:8)
        at process.<anonymous> (node_modules/worker-farm/lib/child/index.js:47:3)
        at emitTwo (events.js:87:13)
        at process.emit (events.js:172:7)
        at handleMessage (internal/child_process.js:686:10)
        at Pipe.channel.onread (internal/child_process.js:440:11)

async function does not working proparly

I tryed to test a little unit that handle dispatches after promise returned in a sync way, but for some reason, I am always get an empty actions array from store.getActions(). Can someone help me?
btw, the action is:

export function firstRefresh(instrumentId) 
{
  return dispatch => 
  {
    Router.refresh(instrumentId, 0)
      .then((data) =>
      {
        try 
        {
          dispatch(setAssetsByMarkets(data.assetsByMarketsObj));
          dispatch(setAssetsAndOptionsFirstTime(data));
          dispatch(setMarkets(data.markets)); 
        } 
        catch (error) 
        {
          console.error('an error catched: ', error);
        }
      }).catch( () => 
      {
        dispatch(setAssetsAndOptions({assets : [], options : []}));
      });
  };
}

and the test is:

describe('async actions', () => {
  it('firstRefresh success', () => {
    const instrumentId = ...,
      serverUrl =...,
      serverPostPath = ...,
      timeStamp = new Date().getTime(),
      replayStatusCode = 200,
      mockReplayBody = {...
      },
      requestHeaders = {
        reqheaders: {...}
      },
      requestBody = {...
      },
      store = mockStore(storeInitialState)

    nock(serverUrl, requestHeaders) 
      .post(serverPostPath)
      .reply(replayStatusCode, {body: mockReplayBody}) 

    const expectedActions = [
      {
        type: 'SET_ASSETS_BY_MARKETS',
        value: mockReplayBody.assetsByMarketsObj
      }, {
        type: 'SET_ASSETS_AND_OPTIONS_FIRST_TIME',
        data: mockReplayBody
      }, {
        type: 'UPDATE_MARKETS',
        value: mockReplayBody.markets
      }
    ]

    store.dispatch(actions.firstRefresh(instrumentId))
    expect(store.getActions()).toEqual(expectedActions)
  })
})

index.d.ts wrong version was merged

Just realized,

In this PR we merged the wrong version of the d.ts definitions:

#39

The right version was the one commented by @asgarddesigns but by mistake we merged the one in the PR.

import {Store} from 'redux';

interface MockStore extends Store {
    getState():any;
    getActions():Array<any>;
    dispatch(action:any):any;
    clearActions():void;
    subscribe():any;
}

declare function configureStore(...args:any[]):(...args:any[]) => MockStore;
export = configureStore;

I have created a new PR containing the right version:

https://github.com/arnaudbenard/redux-mock-store/pull/51/files

testing redux-saga with redux-mock-store

I am trying to write a test using redux-saga and redux-mock-store:

Below is my test:

    import { describe, before, after, it } from 'mocha';
    import { assert, expect } from 'chai';

    import configureMockStore from 'redux-mock-store';

    import { applyMiddleware, compose } from 'redux';

    import createSagaMiddleware from 'redux-saga';

    import fetch from 'isomorphic-fetch';
    import fetchMock from 'fetch-mock';

    import reducer from '../app/reducers';

    import * as actions from '../app/actions/winratio-actions';

    import rootSaga from '../app/sagas';

    const sagaMiddleware = createSagaMiddleware();

    const mockStore = configureMockStore(
      reducer,
      compose(
        applyMiddleware(sagaMiddleware)
      ));


    describe('fetch results', () => {
      after(() => {
        fetchMock.restore();
      });

      it("should call failure action", () => {
        fetchMock.mock('http://localhost:4040/api/results', 501);

        const store = mockStore({});

        store.runSaga = sagaMiddleware.run;

        store.runSaga(rootSaga);

        store.dispatch(actions.loadResultsPage());

        //expect(store).to.not.be.null;
      });
    });

But I get the following error message:

fetch results should call failure action:
     TypeError: middleware is not a function
      at node_modules/redux/lib/applyMiddleware.js:49:16
      at Array.map (native)
      at node_modules/redux/lib/applyMiddleware.js:48:27
      at mockStore (node_modules/redux-mock-store/lib/index.js:70:12)
      at Context.<anonymous> (results-test.js:36:19)

The only examples I can find online use redux-thunk:

      const middlewares = [ thunk ];
      const mockStore = configureMockStore(middlewares);

How do I configure the mock store to use redux-saga?

Exported external package typings file 'redux-mock-store/index.d.ts' is not a module. Please contact the package author to update the package definition

I have downloaded redux-mock-store and it include a definition, when you attempt to use it provides the following error:

Exported external package typings file 'C:/Test/node_modules/redux-mock-store/index.d.ts' is not a module. Please contact the package author to update the package definition

We have implemented a manual typing for redux-mock-store, that worked fine for us:

/// <reference path="../../typings/globals/redux/index.d.ts"/>

declare module "redux-mock-store" {
    interface MockStore extends Redux.Store {
        getState(): any;
        getActions(): Array<any>;
        dispatch(action: any): any;
        clearActions(): void;
        subscribe(): any;
    }

    function configureStore(...args: any[]) : (...args: any[]) => MockStore;
    export = configureStore;
}

This index.d.ts is providing conflicts (even excluding node_modules folders), in our case we are manually deleting that file whenever we install the package.Could it be a good idea to remove the d.ts from redux-mock-store, review it and an updated on to the typings repository?

No longer works with redux-thunk

The following test case doesn't work (and it should IMO). I was able to test code like this in v0.6, but can't in the new v1.0.2

  it('should work with redux-thunk', (done) => {
    function success() {
      return {
        type: 'FETCH_DATA_SUCCESS'
      };
    }
    function asyncAction() {
      return dispatch => {
        setTimeout(() => {
          dispatch(success());
        }, 10);
      };
    }
    const middlewares = [thunk];
    const mockStore = configureMockStore(middlewares);
    const store = mockStore({});
    store.dispatch(asyncAction()).then(() => {
      expect(store.getActions()[0]).toEqual(success())
      done();
    });
  })

Thanks for this great library BTW!

TypeError: createStore is not a function

My issue is related to:
#59

├── [email protected]
├── [email protected]
├── [email protected]

I followed the steps to resolve the same errors experienced by that issue, but the following test still produces an error for me:

import createSagaMiddleware from 'redux-saga'
import configureStore from 'redux-mock-store'
import {applyMiddleware} from 'redux'

const testingRoot = "http://localhost:9090";

describe('async actions', () => {

    afterEach(() => {
        nock.cleanAll()
    });

    it('triggers RESPONSE_FILTER_CHANGE_WITH_OPERATORS_SUCCESS when fetchTransmissions completes successfully', () => {

        const sagaMiddleware = createSagaMiddleware();
        const mockStore = configureStore([applyMiddleware(sagaMiddleware)]);
        // sagaMiddleware.run(WaterlevelSagas);

        nock.disableNetConnect();
        const mockedResponse = WaterlevelMockData;
        nock(testingRoot)
            .get(Config.waterlevelCatalog.url.stagedConfig.waterlevelCatalog.url.staged)
            .reply(200, mockedResponse);

        // const fullState = Immutable.fromJS({transmission: {}, operator: {}});
        const expectedActions = [
            {type: FilterActions.REQUEST_FILTER_CHANGE_BY_CATEGORY},
            {type: FilterActions.RESPONSE_FILTER_CHANGE_WITH_OPERATORS_SUCCESS}
        ];

        const store = mockStore({});
        return store.dispatch(FilterActions.requestFilterChangeByCategory(FilterConstants.category.staged))
            .then(() => {
                store.getActions().should.deep.equal(expectedActions)
            });
    })
});

The following line:

const  store = mockStore({});

produces the following error in my test:

  1) async actions triggers RESPONSE_FILTER_CHANGE_WITH_OPERATORS_SUCCESS when fetchTransmissions completes successfully:
     TypeError: createStore is not a function
      at node_modules/redux/lib/applyMiddleware.js:38:19
      at node_modules/redux/lib/applyMiddleware.js:51:63
      at mockStore (node_modules/redux-mock-store/lib/index.js:79:12)
      at Context.<anonymous> (src/app/WaterlevelSagas-spec.js:54:23)

Any idea on where "createStore" comes into play here and how to resolve this? I haven't used "createStore" anywhere in my test.

Done not being called if test fail in subscribe callback

Hi, I tried your examples and I realize mocha is not catching the error thrown if i used subscribe, also the done callback is not being called. Here is what I used to test this. I wonder if I did anything wrong or if I need to do anything extra for mocha to register these errors. Thanks
screenshot at jun 21 16-58-06

throwing error when using redux-multi

#40

This commit added:

if (typeof action.type === 'undefined') {
  throw new Error(
    'Actions may not have an undefined "type" property. ' +
    'Have you misspelled a constant?'
  );
}

This will throw if you are using arrays that redux-multi will handle e.g:

[ 
  { type: 'action1',
    payload: { id: '1234' } 
  },
  { type: 'action2',
    payload: { id: '5678' } 
  } 
]

Typescript definition removal not published?

Hi,

I'm getting some errors when transpiling the project, just checked the repository and found that you have removed the d.ts file and recommend using the typings one:

9e1d014

But if I just go via npm install I can see that the .d.ts is still on the local files installed, Is there a new version pending to be published on npm?

Thanks

TypeError: mockStore is not a function

Hey there ! I'm getting an issue with the library (i'm using Jest). Here is the code :

import * as actions from '../actions'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'

const middlewares = [thunk]
const mockStore = configureMockStore(middlewares)

describe('Dataset actions', () => {
    it('compareMutuallyExclusiveKeys - default parameters', () => {
        const expectedActions = [{
            type: actions.COMPARE_MUTUALLY_EXCLUSIVE_KEYS,
            payload: {
                mutually_exclusive_keys: [],
                meta: {}
            }
        }]
        const store = mockStore({})
        return store.dispatch(actions.compareMutuallyExclusiveKeys())
            .then(() => {
                expect(store.getActions()).toEqual(expectedActions)
            })
    })
})

And the error :

TypeError: mockStore is not a function

Tried to upgrade redux-thunk (2.0.1) and redux-mock-store (1.1.4), but still getting the error...
Thanks for your help !

Test run twice when an error is reported?

For some reasons, when a test fails, it seems to be run twice (or at least it sends twice done(e)).

Moreover, the error is very hard to read. Would it be possible to improve the error?

Testing nested promises

Hi,
I'm wondering if it's possible to test nested promises:
eg. response.json() - it's a promise which can be invoked after fetch promise,
however if I create "then" method for "store.dispatch" the nested promise won't get executed, is it possible to wait until it's executed?
Regards

redux-logger getting used within redux-mock-store?

In my regular application I have:

import createLogger from 'redux-logger';

const logger = createLogger();

const enhancer = compose(
  applyMiddleware(thunk, logger),
  persistState(
    window.location.href.match(
      /[?&]debug_session=([^&#]+)\b/
    )
  )
);

export default function configureStore(initialState) {
  const store = createStore(rootReducer, initialState, enhancer);

  if (module.hot) {
    module.hot.accept('../reducer', () => {
      store.replaceReducer(require('../reducer').default);
    });
  }

  return store;

But within my tests I have

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import fetchMock from 'fetch-mock';

const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);

But in my terinal window and withink Karma's Chrome Browser I am getting redux-logger details printed out. LOG: '%c prev state', 'color: #9E9E9E; font-weight: bold', Object{auth: Object{accessToken: null, userId: null, isAuthenticated: false, isAuthenticating: false, statusText: null}, form: Object{}, header: Object{showAside: false}, routing: Object{locationBeforeTransitions: null}, user: Object{isFetching: false, errors: []}}

I'm not adding redux-logger to my configureMockStore, only my real store which I am not using for my tests. Is there any way to get rid of redux-logger for tests?

Can't test for no action dispatched?

Is there a way to test that there are no actions? My function may have a condition before dispatching the action.

it('dispatches no actions', (done) => {
    const store = mockStore({}, [], done);

    store.dispatch( 
        (dispatch) => {}
    );
});

This test fails with:
Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

done() is called in error case even when not provided

The mock store accepts either undefined or a function as the done parameter. It also checks for done before calling it in the try case. However it doesn't check in the catch case. So if you don't supply a function and you have an error, you will get a done is not a function error.

Very helpful library, by the way.

Making the library framework agnostic

I have noticed that there are multiple bugs related to how testing frameworks handle errors. I have built this library for mocha but it looks like we need to make it work with Jasmine and tape. I would love to get a conversation started on how we can make the library support multiple frameworks.

Do you have examples of framework agnostic testing libraries?
Or
Should we make forks for every testing framework?

Related issues

#12
#13
#16
#21

cc/ @marr @jdmunro @HowardLoTW @dara76

done() not being called

I have 2 test cases and the second one will not pass and throw

Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

Here is my code snippet:

    it('creates FETCH_TODOS_SUCCESS when fetching todos has been done', (done) => {
        const expectedActions = [
            {type: TodoConstants.GET_TODOS_REQUEST},
            {type: TodoConstants.GET_TODOS_SUCCESS, todos: [
                {
                    id: 1, text: 'todo1', isDone: false
                },
                {
                    id: 2, text: 'todo2', isDone: true
                }
            ]}
        ];

        const store = mockStore({todos: []}, expectedActions, done);
        store.dispatch(actions.fetchTodos());
    });

    it('post ADD_TODO_SUCCESS when add todo has been done', (done) => {
        const expectedActions = [
            {type: TodoConstants.ADD_TODO_REQUEST, text: 'todo3'},
            {type: TodoConstants.ADD_TODO_SUCCESS, todo: {
                id: 3, text: 'todo3', isDone: false
            }}
        ];

        const store = mockStore({todos: []}, expectedActions, done);
        store.dispatch(actions.addTodo('todo3'));
    });

I duplicated the 'get' test case, only the first 'get' test case can pass.
then I removed the duplicate test case and put the 'post' test case in front of the 'get' test case, neither test case can pass.

My temporary solution is calling the done() function explicitly for each test case.

Error: cannot find babel preset

we are using redux-mock-store in a react native project and we are running into this issue:

cannotfindpreset

we are not using babel-preset-es2015 in our project, but we must install it in order to make this error go away.

Possible cause: I have looked at the package.json file for this package and noticed all the dependencies are listed as devDependencies -- as far as I know , devDependencies for third party modules do not get installed. Additionally, the error message suggests babel is looking for files relative to node_modules/redux-mock-store first. A possible fix would be to list babel-preset-es2015 as a regular dependency instead of a devDependency.

Properly test with redux-mock-store

Hello,

I have an action like this

export function getItems() {
  return {
    type: GET_ITEMS,
    payload: {
      promise: axios.get(`${domain}:${port}/api/items`)
    }
  };
}

and my testing code

import promiseMiddleware from 'redux-promise-middleware';
import nock from 'nock';
import configureStore from 'redux-mock-store';
import { domain, port } from '../../config/environment';

import { GET_ITEMS_START,
         GET_ITEMS_SUCCESS } from '../../constants/items';
import { getItems } from './items';

const promise = promiseMiddleware({
  promiseTypeSuffixes: ['START', 'SUCCESS', 'ERROR']
});


const mockStore = configureStore([promise]);

describe('Items Action Creator', () => {
  describe('Get Items', () => {
    it('should create GET_ITEMS_SUCCESS action after successfully getting items', (done) => {
      nock(`${domain}:${port}`)
        .get('/api/items')
        .reply(200, {
          _id: '1',
          text: 'Make Eggs',
          completed: false
        });

      const expectedActions = [
        { type: GET_ITEMS_START },
        { type: GET_ITEMS_SUCCESS, payload: {
          data: {  _id: '1', text: 'Make Eggs', completed: false }
        }}
      ];

      const store = mockStore({}, expectedActions, done);
      store.dispatch(getItems());
    });
  });

This is the result that was being returned

  1) Items Action Creator Get Items should create GET_ITEMS_SUCCESS action after successfully getting items:

      Error: Expected { payload: { config: { headers: {}, method: 'get', timeout: 0, transformRequest: [ [Function] ], transformResponse: [ [Function] ], url: 'http://localhost:3000/api/items', withCredentials: undefined }, data: { _id: '1', completed: false, text: 'Make Eggs' }, headers: {}, status: 200, statusText: 'OK' }, type: 'GET_ITEMS_SUCCESS' } to equal { payload: { data: { _id: '1', completed: false, text: 'Make Eggs' } }, type: 'GET_ITEMS_SUCCESS' }
      + expected - actual

       {
         "payload": {
      -    "config": {
      -      "headers": {}
      -      "method": "get"
      -      "timeout": 0
      -      "transformRequest": [
      -        [Function]
      -      ]
      -      "transformResponse": [
      -        [Function]
      -      ]
      -      "url": "http://localhost:3000/api/items"
      -      "withCredentials": [undefined]
      -    }
           "data": {
             "_id": "1"
             "completed": false
             "text": "Make Eggs"
           }
      -    "headers": {}
      -    "status": 200
      -    "statusText": "OK"
         }
         "type": "GET_ITEMS_SUCCESS"
       }

How do I just make sure that only the "data" property that is being compared instead of the whole payload object

Mock Store State is not being updated

I'm having the same issue as #45. Maybe I'm not understanding this correctly, but does mock-store actually run the actions through the reducers anywhere? I'm not seeing how they're ever connected with a setup like this:

import configureStore from 'redux-mock-store'
import thunk from 'redux-thunk'
const mockStore = configureStore([thunk])
const store = mockStore({ ...state })
console.log(store.getState()) // => { ...state }
store.dispatch(someAction())
console.log(store.getActions()) // => [ someAction() ] The action does show up here!
console.log(store.getState()) // => { ...state } But this is the same unchanged state as above

Store's getActions method is returning empty during unit test

I have no idea why this action is array is becoming empty, especially when I log it inside the dispatch action it seems to push it in just fine. Somewhere inside the dispatch of the action it is getting cleared. If anybody has any ideas that would be a great help.

Here is the unit test:

let response: any = [{ 'displayOrder': -1, 'formTypeId': 3717, 'id': 829, 'name': 'a', 'parentId': 3717 }];
let prefix: string ='TestString'
it('should call RECEIVE_DATA when fetching has been done', () => {
    nock(someURL)
        .get('someURL')
        .reply(200, response);

    let collection: Array<any> = response;
    const expectedActions = [
        {
            type: prefix + '_RECEIVE_DATA',
            data: Immutable.List<IChildEntity>(collection),
        }
    ]
    const store = mockStore({ MetadataField: [] });
    let id: number = 3717;

    return store.dispatch(IChildEntityActions.initializeData(prefix, id))
        .then(
        () => { // return of async actions
            Chai.expect(store.getActions()).to.deep.equal(expectedActions);
        })
})

})

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.