Как выполнить функцию внутри компонента без сохранения состояния для тестирования в Jest и Enzyme

У меня есть родительский компонент, который я обернул с помощью Recompose withHandlers HOC. У меня есть функция с именем removeGiftHandler, которую я хочу передать дочернему компоненту в качестве обратного вызова, который изменит состояние, хранящееся в реквизитах родительского компонента (с использованием withState).

В настоящее время я тестирую родительский компонент, в частности функцию removeGiftHandler. Проблема в том, что, поскольку функция передается дочернему компоненту, мне не нужно моделировать событие. Также, если бы это был компонент класса, я мог бы использовать wrapper.instance().removeGift(id), и не было бы никаких проблем. Учитывая, что это функциональный компонент без сохранения состояния, это не так.

Вот код компонента:

const App = ({ addGiftHandler, state: { gifts } }) => (
    <div>
        <h1>Gift Giver</h1>
        <ListGroup>
            {map(
                ({ id }) => (
                    <ListGroupItem key={id}>
                        <Gift />
                    </ListGroupItem>
                ),
                gifts
            )}
        </ListGroup>
        <Button outline onClick={addGiftHandler}>
            Add Gift
        </Button>
    </div>
)

export default compose(
    withEnhancedState(INITIAL_STATE),
    withHandlers({
        addGiftHandler: ({ state: { gifts }, updateState }) => () =>
            updateState({ gifts: [...gifts, { id: inc(length(gifts)) }] }),
        removeGiftHandler: ({ state: { gifts }, updateState }) => id => () =>
            updateState({ gifts: filter(gift => gift.id !== id, gifts) }),
    })
)(App)

После того, как removeGiftHandler будет должным образом протестирован, план состоит в том, чтобы передать его компоненту Gift.

А вот соответствующий код для тестов:

import React from 'react'
import { shallow } from 'enzyme'
import { length } from 'ramda'

import App from '.'

const getBaseApp = app =>
    app
        .dive()
        .dive()
        .dive()

describe('App', () => {
    const app = shallow(<App />)
    const baseApp = getBaseApp(app)

        //...

        describe('and the user wants to remove the added gift', () => {
            beforeEach(() => {
                //-----> trigger removeGiftHandler somehow <-----
            })

            it('removes the gift from `state`', () => {
                expect(app.props().state.gifts).toEqual([])
            })
        })
    })
})

Примечание. baseApp - это базовый компонент без компонентов "Восстановить HOC".

Может кто-нибудь помочь мне с этой проблемой?


person avatarhzh    schedule 11.01.2019    source источник
comment
Возможно, вы можете просто нырнуть 2 раза вместо 3, чтобы получить часть withHandlers, вызвать функцию и проверить, обновилось ли состояние, но я не уверен, что это сработает. Мы делаем это так, чтобы отделить представление от перекомпоновки, поэтому вместо возврата compose(...)(Component) у нас есть только один файл, возвращающий compose(...), один файл, возвращающий компонент, и index.js, который просто возвращает logic(View). При таком подходе мы можем легко протестировать часть перекомпоновки и изолированную функцию рендеринга.   -  person Andreas Köberle    schedule 11.01.2019
comment
Как провести тестирование части compose (...) отдельно?   -  person avatarhzh    schedule 11.01.2019
comment
@ AndreasKöberle Дайвинг дважды действительно сработал. Спасибо, что нашли время написать суть. Мне жаль, что я не ответил вам раньше. Я обязательно сохраню этот шаблон тестирования compose (...) отдельно в глубине души на тот случай, если мне понадобится его использовать когда-нибудь в будущем.   -  person avatarhzh    schedule 15.01.2019
comment
Хорошо, тогда я предоставлю это как ответ.   -  person Andreas Köberle    schedule 15.01.2019


Ответы (1)


Вам нужно нырнуть 2 раза вместо 3, чтобы достичь withHandlers HOC. На реквизите вы можете вызвать функцию и проверить, правильно ли обновлено состояние.

person Andreas Köberle    schedule 15.01.2019