У меня есть код для usePrevious из Интернета. Код для usePrevious выглядит так:
export const usePrevious = (value) => {
const ref = useRef();
useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
};
Теперь я учусь тестировать реакцию с шуткой и энзимом. Итак, я попытался протестировать usePrevious и получил некоторые проблемы. Вот мой тестовый пример:
import React from 'react';
import { render } from 'enzyme';
import { usePrevious } from './customHooks';
const Component = ({ children, value }) => children(usePrevious(value));
const setup = (value) => {
let returnVal = '';
render(
<Component value={value}>
{
(val) => {
returnVal = val;
return null;
}
}
</Component>,
);
return returnVal;
};
describe('usePrevious', () => {
it('returns something', () => {
const test1 = setup('test');
const test2 = setup(test1);
expect(test2).toBe('test');
});
});
Когда выполнение теста завершается, я получаю такую ошибку:
Expected: 'test', Received: undefined
Может ли кто-нибудь сообщить мне, почему я получаю undefined и правильный ли это способ протестировать пользовательские хуки в ответ?
После предложения из комментариев от @Dmitrii G я изменил свой код, чтобы повторно визуализировать компонент (ранее я повторно монтировал компонент).
Вот обновленный код:
import React from 'react';
import PropTypes from 'prop-types';
import { shallow } from 'enzyme';
import { usePrevious } from './customHooks';
const Component = ({ value }) => {
const hookResult = usePrevious(value);
return (
<div>
<span>{hookResult}</span>
<span>{value}</span>
</div>
);
};
Component.propTypes = {
value: PropTypes.string,
};
Component.defaultProps = {
value: '',
};
describe('usePrevious', () => {
it('returns something', () => {
const wrapper = shallow(<Component value="test" />);
console.log('>>>>> first time', wrapper.find('div').childAt(1).text());
expect(wrapper.find('div').childAt(0).text()).toBe('');
// Test second render and effect
wrapper.setProps({ value: 'test2' });
console.log('>>>>> second time', wrapper.find('div').childAt(1).text());
expect(wrapper.find('div').childAt(0).text()).toBe('test');
});
});
Но все равно получаю ту же ошибку
Expected: "test", Received: ""
Тесты проходят, когда вводится время ожидания:
import React from 'react';
import PropTypes from 'prop-types';
import { shallow } from 'enzyme';
import { usePrevious } from './customHooks';
const Component = ({ value }) => {
const hookResult = usePrevious(value);
return <span>{hookResult}</span>;
};
Component.propTypes = {
value: PropTypes.string,
};
Component.defaultProps = {
value: '',
};
describe('usePrevious', () => {
it('returns empty string when component is rendered first time', () => {
const wrapper = shallow(<Component value="test" />);
setTimeout(() => {
expect(wrapper.find('span').text()).toBe('');
}, 0);
});
it('returns previous value when component is re-rendered', () => {
const wrapper = shallow(<Component value="test" />);
wrapper.setProps({ value: 'test2' });
setTimeout(() => {
expect(wrapper.find('span').text()).toBe('test');
}, 0);
});
});
Я не большой поклонник использования settimeout, поэтому чувствую, что, вероятно, делаю какую-то ошибку. Если кто-то знает решение, которое не использует settimeout, не стесняйтесь публиковать здесь. Спасибо.
test
вместоundefined
- person Vishal   schedule 30.11.2019mount()
. У поверхностного рендерера есть известные проблемы с разрушениемuseEffect
, я удивлен, что он работает с тайм-аутом в качестве временного решения. - person skyboyer   schedule 30.11.2019mount()
вместоshallow()
мне не нужно устанавливать тайм-аут. Спасибо за помощь. Пожалуйста, опубликуйте его как ответ, чтобы я мог закрыть вопрос, и кто-то в будущем, наткнувшись на это, может найти здесь решение. - person Vishal   schedule 30.11.2019