JiSeven
@JiSeven
web-developer

Как тестировать такие реактовские события кликов в enzyme?

У меня есть простой компонент кнопки, который по клику бросает flux-экшен.

import React from 'react';
import Button from 'components/Button';

import { loginUser } from 'actions/user';

const LoginButton = () => (
  <Button onClick={() => loginUser('UserName')}>
    Войти
  </Button>
);

export default LoginButton;


Как можно протестировать то, что функция loginUser будет вызвана по клику? Как вообще проверять внешние функции на вызов? Или забить вообще на такие тесты сославшись на тесты самого реакта?

Я использую enzyme, mocha, chai, sinon.
  • Вопрос задан
  • 762 просмотра
Пригласить эксперта
Ответы на вопрос 1
maxfarseer
@maxfarseer
https://maxpfrontend.ru, обучаю реакту и компании
Игорь, отвечу вам на вопрос - "как в таком случае проверить, что такой-то такой-то экшен отправляется в диспетчер?", который всплыл в комментариях, и на который я изначально был настроен =) Тестировать нужно. Тестируется все по документации

Разберем пример тестирования асинхронного экшен-крейтора на получение списка продуктов:

Для начала код AC (action creator)
export function getProducts() {
  return dispatch => {
    dispatch({ type: PRODUCTS_GET_REQUEST })

    return request.get(`${API_ROOT_V1}/api/v1/products/getAll`)
      .then(res => {
        if (!res.ok) {
          dispatch({ type: PRODUCTS_GET_FAILURE })
          dispatch(showNotification({
            status: 'err',
            text: 'something going wrong',
          }))

        } else {
          dispatch({
            type: PRODUCTS_GET_SUCCESS,
            data: normalize(res.body.data, schema.arrayOfProducts),
          })
        }
      }, err => {
        dispatch({ type: PRODUCTS_GET_FAILURE })
        dispatch(showNotification({
          status: 'err',
          text: err.message,
        }))
      })
  }
}


Получается, для тестирования функции getProducts, которая является AC, мы напишем тест, в котором ожидаем в случае успешного выполнения:
а) что store достигло событие 'PRODUCTS_GET_REQUEST'
б) что store достигло событие 'PRODUCTS_GET_SUCCESS' с некой data (у меня она еще нормализуется, но это не суть)

Для этого, нам потребуется redux-mock-store (взято так же из документации).
Собственно, сам тест:

it('creates PRODUCTS_GET_SUCCESS when get products has been done', () => {

      const data = [
        {
          '_id': '5763e6eccfdb2e9d4baa58ef',
          'name': 'Product A',
          'description': 'Description of A',
          'img': 'no-photo',
          '__v': 0,
          'providers': [],
        },
        {
          '_id': '5763e6eccfdb2e9d4baa58f0',
          'name': 'Product B',
          'description': 'Description of B',
          'img': 'no-photo',
          '__v': 0,
          'providers': [],
        },
      ]

      nock(`${API_ROOT_V1}`)
        .get('/api/v1/products/getAll')
        .reply(200, { data })

      const expectedActions = [
        { type: PRODUCTS_GET_REQUEST },
        { type: PRODUCTS_GET_SUCCESS, data: normalize(data, schema.arrayOfProducts) },
      ]

      const store = mockStore([])

      return store.dispatch(getProducts())
        .then( () => expect(store.getActions()).to.deep.equal(expectedActions) )
    })


То есть, отвечая на вопрос:
как в таком случае проверить, что такой-то такой-то экшен отправляется в диспетчер

1) const store = mockStore([])
2) store.getActions()
3) сравниваем полученное в п.2 с тем, что ожидаем.

Здесь я попутно использовал nock для "мока" запроса к API. И немного подробнее описал ожидаемую "фейковую" дату (хотя это было не обязательно). Главное суть: мы ожидаем, что некоторые "экшены" достигнут стора. Это и протестировали.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы