Sergei Klinov
Sergei Klinov

Reputation: 798

Redux store is not updated during integration test

I'm trying to do integration tests for the React-Redux application using Jest and Enzyme. The app itself works correctly and the Redux store is updated correctly after component dispatching an action. But when I run an integration test, the store has an initial value after the action being dispatched.

Here's my test file:

import SendMessageSendsay from '../utils/sendMessage'
import {testStore} from '../utils'
import {sendMessage } from '../redux/actions/messageActions'

jest.mock('../utils/sendMessage');

describe('sendMessage action', ()=> {
    const message = {
        subject: 'Message subject',
        toEmail: '[email protected]'
    }

    test('Send message: Should update store correctly', () => {
        const store = testStore();
        const referenceState = {
            messages: {
              messages: [
                {
                  date: '2019-08-30T11:36:14.813Z',
                  subject: 'Message subject',
                  trackId: '95'
                }
              ],
              isSent: true,
              prevToEmail: '[email protected]'
            }
          }
        SendMessageSendsay.mockResolvedValue({'track.id' : '95' })       
        store.dispatch(sendMessage(message))
        const newState = store.getState();
        console.log(newState);
        expect(newState).toBe(referenceState);  

    })
});

And I get these results:

● sendMessage action › Send message: Should update store correctly

    expect(received).toBe(expected) // Object.is equality

    - Expected
    + Received

      Object {
        "messages": Object {
    -     "isSent": true,
    -     "messages": Array [
    -       Object {
    -         "date": "2019-08-30T11:36:14.813Z",
    -         "subject": "Message subject",
    -         "trackId": "95",
    -       },
    -     ],
    -     "prevToEmail": "[email protected]",
    +     "isSent": false,
    +     "messages": Array [],
    +     "prevToEmail": "",
        },
      }

where received is the initial state in my reducer. Here's my action:

export const sendMessage = (message) => (dispatch) => {
  sendMessageSendsay(message)
  .then((res) => dispatch(
    {
      type: SEND_MESSAGE,
      message: {
        date: new Date(),
        subject: message.subject,
        trackId: res['track.id']
      },
      prevToEmail: message.toEmail
    }
  ))
}

And here's the reducer:

export const initialState = {
    messages : [],
    isSent: false,
    prevToEmail: ''
}

export default (state = initialState, action) => {
    switch (action.type) {
        case SEND_MESSAGE: 
        {
            return {
                ...state,
                messages: [
                    ...state.messages,
                    action.message
                ],
                isSent: true,
                prevToEmail: action.prevToEmail
            }; 
        }

Upvotes: 1

Views: 1319

Answers (1)

Sergei Klinov
Sergei Klinov

Reputation: 798

Based on @HMR comment I modified the action to this:

export const sendMessage = (message) => (dispatch) => {
  return new Promise((resolve) => {
    sendMessageSendsay(message)
    .then((res) => resolve(dispatch(
      {
        type: SEND_MESSAGE,
        message: {
          date: new Date(),
          subject: message.subject,
          trackId: res['track.id']
        },
        prevToEmail: message.toEmail
      }
    )))
  })
}

And test file to this:

import SendMessageSendsay from '../utils/sendMessage'
import {testStore} from '../utils'
import {sendMessage } from '../redux/actions/messageActions'

jest.mock('../utils/sendMessage');

describe('sendMessage action', ()=> {
    const message = {
        subject: 'Message subject',
        toEmail: '[email protected]'
    }

    test('Send message: Should update store correctly', () => {
        const store = testStore();
        const referenceState = {
            messages: {
              messages: [
                {
                  subject: 'Message subject',
                  trackId: '95'
                }
              ],
              isSent: true,
              prevToEmail: '[email protected]'
            }
          }

        SendMessageSendsay.mockResolvedValue({'track.id' : '95' })       

        return store.dispatch(sendMessage(message))
        .then(() => {
          const newState = store.getState();
          expect(newState).toMatchObject(referenceState); 
        })

    })
});

I used toMatchObject() istead of toEqual() to work around timestamp.

Upvotes: 1

Related Questions