#javascript #reactjs #typescript #jestjs
#javascript #reactjs #typescript #jestjs
Вопрос:
export const Comp = () => {
const {val, change} = useContext(ProviderContext)
return (
<TextField>
onChange={({target}) => {
change(target)
}}
value={val}
</TextField>
);
}
describe('test', ()=>{
let container = document.createElement('div')
document.body.appendChild(container);
//This doesn't work since it's not a react component
const [val, setVal] = useState();
const change = (e)=>{
setVal(e.value)
}
it('test', ()=>{
act(() => {
render(
<ProviderContext.Provider value={{
val,
change,
}}>
<Comp />
</ProviderContext.Provider>
), container
});
})
})
Когда пользователи вводят текст в поле, он вызывает onChange текстового поля, который вызывает функцию «изменить» из контекста, которая обновляет состояние ‘val’ из контекста.
Спасибо
Комментарии:
1. Непонятно, зачем вам для этого нужен useState. В чем именно проблема с предоставлением необработанного
val
значения?2. Потому что компоненту Comp нужен хук. Он перезапускается при вызове setVal
3. Похоже, это проблема XY. Компоненту не требуется перехват, потому что ему нужно только значение. Если вам нужно повторно отобразить дерево компонентов, это можно сделать несколькими способами. Вы не опубликовали свои настройки тестирования, поэтому я предполагаю, что вы используете тестовые утилиты React низкого уровня. В этом случае это делается путем обертывания компонента фиктивным компонентом, если он функционален, он будет использовать useState для запуска повторного рендеринга, и таким образом вы избежите проблемы, указанной в вопросе. Если вы используете библиотеки более высокого уровня, такие как RTL, которые предлагает ответ, они предоставляют свои собственные способы (повторного) рендеринга, в которых нет необходимости
act
,useState
и т.д.4. Да, я предположил, что вам нужен state setter только для повторного отображения компонента извне. Здесь вы могли бы просто предоставить Jest spy как
change
и утверждать, что он был вызван. Поскольку способ обновления контекста в новом состоянии гарантируется React, я не вижу смысла в его тестировании конкретно с помощью useState. Вы, конечно, можете пойти этим путем, но удобнее проводить тестирование blackbox с помощью RTL, чем с помощью простого средства визуализации React, поскольку первое является надмножеством последнего.5. У RTL есть
rerender
, у Enzyme естьsetProps
. Если вы их не используете, вам нужно заново изобрести колесо с фиктивной оболочкой компонента и использоватьforceUpdate
на нем.
Ответ №1:
Вы можете использовать renderHook из библиотеки тестирования react
import { renderHook, act } from '@testing-library/react-hooks'
it('test', ()=>{
const [val, setVal] = renderHook(() => useState());
act(() => {
render(
<ProviderContext.Provider value={{
val,
}}>
<Comp />
</ProviderContext.Provider>
), container
});
})
Комментарии:
1. renderHook обычно необходим для тестирования пользовательских перехватов. Поскольку был предложен RTL, он обеспечивает повторную визуализацию и вообще не нуждается в useState трюке.
2. @EstusFlask что, если мы передаем установщик из useState, как мы это делаем?