React 컴포넌트에서 프로펠러 업데이트를 테스트하는 방법
React 구성 요소 프로펠러 업데이트를 테스트하는 올바른 방법은 무엇입니까?
여기 제 시험기구가 있습니다.
describe('updating the value', function(){
var component;
beforeEach(function(){
component = TestUtils.renderIntoDocument(<MyComponent value={true} />);
});
it('should update the state of the component when the value prop is changed', function(){
// Act
component.props.value = false;
component.forceUpdate();
// Assert
expect(component.state.value).toBe(false);
});
});
정상적으로 동작하고 테스트에 합격하지만 리액트 경고 메시지가 표시됩니다.
'Warning: Dont set .props.value of the React component <exports />. Instead specify the correct value when initially creating the element or use React.cloneElement to make a new element with updated props.'
테스트하려는 것은 속성 업데이트일 뿐 다른 속성을 가진 요소의 새 인스턴스를 만드는 것은 아닙니다.이 숙박업소를 갱신할 수 있는 더 좋은 방법이 있을까요?
AirBnB의 효소 라이브러리는 이 질문에 대한 우아한 해결책을 제공합니다.
얕은 래퍼 또는 jsdom 래퍼에서 호출할 수 있는 setProps 메서드를 제공합니다.
it("Component should call componentWillReceiveProps on update", () => {
const spy = sinon.spy(Component.prototype, "componentWillReceiveProps");
const wrapper = shallow(<Component {...props} />);
expect(spy.calledOnce).to.equal(false);
wrapper.setProps({ prop: 2 });
expect(spy.calledOnce).to.equal(true);
});
동일한 컨테이너 노드에서 다른 소품으로 요소를 다시 렌더링하는 경우 다시 마운트되는 대신 업데이트됩니다.React.render를 참조하십시오.
당신의 경우,ReactDOM.render
대신 직접TestUtils.renderIntoDocument
후자는 호출될 때마다 새로운 컨테이너 노드를 생성하고, 따라서 새로운 컴포넌트도 만듭니다.
var node, component;
beforeEach(function(){
node = document.createElement('div');
component = ReactDOM.render(<MyComponent value={true} />, node);
});
it('should update the state of the component when the value prop is changed', function(){
// `component` will be updated instead of remounted
ReactDOM.render(<MyComponent value={false} />, node);
// Assert that `component` has updated its state in response to a prop change
expect(component.state.value).toBe(false);
});
주의: 이것이 실제로 소품을 바꾸지는 않습니다.
하지만 제게는 제 논리를 시험해보고 싶었어요componentWillReceiveProps
그래서 전화드렸습니다.myComponent.componentWillReceiveProps(/*new props*/)
직접적으로.
소품이 바뀌었을 때 리액트가 메서드를 호출하는지, 소품이 바뀌었을 때 리액트가 소품을 세팅하는지 테스트할 필요가 없었다.그냥 소품이 전달된 것과 다르면 애니메이션이 트리거된다.
또, 테스트·라이브러리의 회답은 이쪽에서 찾을 수 없었습니다만, 이 호에는 다음과 같은 예가 기재되어 있습니다.
const {container} = render(<Foo bar={true} />)
// update the props, re-render to the same container
render(<Foo bar={false} />, {container})
또는, 현재는 테스트 라이브러리에서도 같은 것을 실현하는 방법을 제공하고 있습니다.
이것은 오래된 질문입니다만, 다른 사람이 우연히 발견했을 경우에 대비해, 다음의 설정이 도움이 되었습니다.
it('updates component on property update', () => {
let TestParent = React.createClass({
getInitialState() {
return {value: true};
},
render() {
return <MyComponent value={this.state.value}/>;
}
});
component = TestUtils.renderIntoDocument(<TestParent/>);
component.setState({value: false});
// Verification code follows
});
그러면 React가 일반적인 컴포넌트 업데이트를 실행합니다.
다음은 ReactDOM.render를 사용하지만 함수의 (사용하지 않는) 반환값에 의존하지 않는 솔루션을 보여 줍니다.대신 콜백(ReactDOM.render에 대한 세 번째 인수)을 사용합니다.
브라우저에서 테스트하지 않는 경우 jsdom을 설정합니다.
var jsdom = require('jsdom').jsdom;
var document = jsdom('<!doctype html><html><body><div id="test-div"></div></body></html>');
global.document = document;
global.window = doc.defaultView;
비동기 콜백을 사용한 react-dom 렌더를 사용한 테스트:
var node, component;
beforeEach(function(done){
node = document.getElementById('test-div')
ReactDOM.render(<MyComponent value={true} />, node, function() {
component = this;
done();
});
});
it('should update the state of the component when the value prop is changed', function(done){
// `component` will be updated instead of remounted
ReactDOM.render(<MyComponent value={false} />, node, function() {
component = this;
// Assert that `component` has updated its state in response to a prop change
expect(component.state.value).toBe(false);
done();
});
});
효소를 사용하여 구성요소를 마운트하고 여기에 소품을 추가할 수 있습니다.
import React form 'react';
import component;
import {configure, mount} form 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import {expect} from 'chai';
configure({adapter: new Adapter()});
describe('Testing component', () => {
let wrapper;
beforeEach(() => {
component = mount(<MyComponent value={false} />);
});
it('should update the state of the component when the value prop is changed', function(){
expect(component.props().children.props.value).toBe(false);
});
둘다요.TestUtils.renderIntoDocument
그리고.ReactDOM.render
에서 반환된 값을 사용합니다.ReactDOM.render
. React 문서에 따르면:
ReactDOM.render()는 현재 루트 ReactComponent 인스턴스에 대한 참조를 반환합니다.그러나 이 반환값을 사용하는 것은 레거시이므로 향후 React 버전에서 구성 요소를 비동기식으로 렌더링할 수 있으므로 사용하지 않는 것이 좋습니다.루트 React Component 인스턴스에 대한 참조가 필요한 경우 권장되는 솔루션은 콜백 참조를 루트 요소에 연결하는 것입니다.
이 조언을 받아들여 다음과 같이 하면 어떨까요?
let component, node;
const renderComponent = (props = {}) => {
ReactDOM.render(<MyComponent ref={r => component = r} {...props} />, node);
}
beforeEach(function(){
node = document.createElement('div');
renderComponent({value: true}, node);
});
it('should update the state of the component when the value prop is changed', function(){
// `component` will be updated instead of remounted
renderComponent({value: false}, node);
// Assert that `component` has updated its state in response to a prop change
expect(component.state.value).toBe(false);
});
방법(with)ReactDOM.render(<MyComponent ref=...
는 HOC
언급URL : https://stackoverflow.com/questions/30614454/how-to-test-a-prop-update-on-react-component
'it-source' 카테고리의 다른 글
WordPress 사용자 지정 게시물 목록을 표시하려면 어떻게 해야 합니까? (0) | 2023.04.01 |
---|---|
JS를 테스트하기 위해 레일 각도 프로젝트를 설정하려면 어떻게 해야 합니까? (0) | 2023.04.01 |
내 WordPress 플러그인에서 파일에 쓰기 (0) | 2023.04.01 |
사용 가능한 경우 서버 동기화를 사용하여 Angular.js 앱을 오프라인으로 만드는 방법 (0) | 2023.04.01 |
Angular를 사용하여 URL을 프로그래밍 방식으로 작성하는 방법JS (0) | 2023.04.01 |