response-redux 4.0 теперь использует API контекста, и это здорово!Однако, когда я пытаюсь обновить мой проект, все работает, но мои модульные тесты начинают проваливаться.
Для контекста, это очень скучный «шаблонный» проект, над которым я работаю ради забавы.Для демонстрационных целей это в основном приложение для дел (все мы любим задачи, верно?).
Теперь для своих контейнеров я провожу некоторое модульное тестирование, но очень простое.По сути, я хочу убедиться, что и mapStateToProps, и mapDispatchToProps получают то, что они должны получать.Мне все равно, как, просто они находятся внутри.
Вот мой компонент "ConnectedToDos":
import { injectIntl } from 'react-intl'
import { connect } from 'react-redux'
import { createStructuredSelector } from 'reselect'
import {
addTodo,
completeTodo,
deleteTodo,
loadTodos,
makeGetTodos,
} from './duck'
import ToDos from './view'
const mapStateToProps = createStructuredSelector({
todos: makeGetTodos(),
})
const mapDispatchToProps = {
handleComplete: completeTodo,
handleSubmit: addTodo,
handleDelete: deleteTodo,
requestTodos: loadTodos,
}
export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(ToDos))
Теперь, чтобы проверить это, я использовал следующее:
import React from 'react'
import PropTypes from 'prop-types'
import configureStore from 'redux-mock-store'
import { shallow, mount } from 'enzyme'
import { fromJS } from 'immutable'
import { MemoryRouter } from 'react-router-dom'
import { IntlProvider } from 'react-intl'
import ConnectedToDos from 'modules/ToDos'
describe('Connected <ToDos />', () => {
const initialState = fromJS({
resources: {
todos: [
{ title: 'A todo', description: 'Do me!', id: '1', done: false },
{ title: 'A todo', description: 'Do me!', id: '2', done: true },
{ title: 'A todo', description: 'Do me!', id: '3', done: false },
{ title: 'A todo', description: 'Do me!', id: '4', done: true },
],
},
})
let mockStore
let store
beforeAll(() => {
mockStore = configureStore([])
store = mockStore(initialState)
})
it('props should match mapStateToProps', () => {
const wrapper = shallow(<ConnectedToDos store={store} />)
expect(wrapper.prop('todos')).toEqual(initialState.getIn(['resources', 'todos']))
})
it('props should match mapDispatchToProps', () => {
const wrapper = mount(
<IntlProvider locale="en" messages={{ en: {} }}>
<MemoryRouter>
<ConnectedToDos />
</MemoryRouter>
</IntlProvider>,
{
context: { store },
childContextTypes: { store: PropTypes.object.isRequired },
},
)
wrapper.find('input[type="checkbox"]').first().simulate('change')
wrapper.find('form').simulate('submit')
wrapper.find('Icon[name="DELETE"]').first().simulate('click')
const actions = store.getActions()
const todosActions = actions.filter(action => action.type.includes('/todos/'))
expect(todosActions).toHaveLength(4)
})
})
Однако теперь выдается хорошее предупреждение:
Инвариантное нарушение: Не удалось найти «store» в контексте «Connect (InjectIntl (ToDos)))».Либо оберните корневой компонент в <Provider>
, либо передайте пользовательский поставщик контекста React в <Provider>
и соответствующий потребитель контекста React в Connect(InjectIntl(ToDos))
в параметрах соединения.
Cool.Но теперь я задаюсь вопросом, как лучше всего протестировать мои контейнеры?
Я пробовал множество способов, последний из которых выглядит следующим образом:
it('props should match mapStateToProps', () => {
const wrapper = shallow(<ConnectedToDos />, { context: { store } })
expect(wrapper.prop('todos')).toEqual(initialState.getIn(['resources', 'todos']))
})
Но это не удается.Кажется, что что бы я ни делал, wrapper.context()
- это всегда пустой объект.
Я не могу скопировать и вставить ВСЕ свой код здесь, но у меня есть репозиторий, который вы можете клонировать и поиграть с собой:https://github.com/enrique-ramirez/react-redux-boilerplate
Тест, который не прошел, включен src/modules/ToDos/tests/index.test.js
.
TL; DR Как я могу проверить свои mapStateToProps
и mapDispatchToProps
, используя новый реактивный редукс?