Enzyme-<input> 값에 액세스하고 설정하는 방법은 무엇입니까?


90

을 사용할 <input>때 값 에 액세스하는 방법에 대해 혼란 스럽습니다 mount. 내 테스트로 얻은 것은 다음과 같습니다.

  it('cancels changes when user presses esc', done => {
    const wrapper = mount(<EditableText defaultValue="Hello" />);
    const input = wrapper.find('input');

    console.log(input.render().attr('value'));
    input.simulate('focus');
    done();
  });

콘솔이 출력합니다 undefined. 그러나 코드를 약간 수정하면 작동합니다.

  it('cancels changes when user presses esc', done => {
    const wrapper = render(<EditableText defaultValue="Hello" />);
    const input = wrapper.find('input');

    console.log(input.val());
    input.simulate('focus');
    done();
  });

물론 input.simulate지금 사용하고 있기 때문에 줄이 실패합니다 render. 제대로 작동하려면 둘 다 필요합니다. 이 문제를 어떻게 해결합니까?

수정 :

내가 언급해야 할 <EditableText />것은 제어 된 구성 요소가 아닙니다. 나는 통과 할 때 defaultValue에 <input />,이 값을 설정하는 것 같다. 위의 두 번째 코드 블록은 값을 출력하고 마찬가지로 Chrome에서 입력 요소를 검사 $0.value하고 콘솔에 입력 하면 예상 값이 표시됩니다.

답변:


99

나는 당신이 원하는 것은 다음과 같습니다.

input.simulate('change', { target: { value: 'Hello' } })

여기 내 소스 입니다.

render()값을 설정 하기 위해 아무 곳이나 사용할 필요가 없습니다 . 그리고 참고로, 당신은 두 개의 다른 것을 사용하고 있습니다 render(). 첫 번째 코드 블록의 하나는 Enzyme에서 ​​가져온 것으로 래퍼 개체에 대한 메서드 mount이며 find제공합니다. 두 번째는 100 % 명확하지는 않지만 아마도 react-dom. Enzyme을 사용하는 경우 shallow또는 mount적절하게 사용하고 renderfrom을 사용할 필요가 없습니다 react-dom.


이 input.render()되지 않는 react-dom렌더링합니다. : 그것은이의 airbnb.io/enzyme/docs/api/ShallowWrapper/render.html
— ffxsam

3
또한, shallow()어떤 이유로 작동하지 않습니다 .. focus이벤트는 참조를 시도하는 메소드를 트리거하지만 this.refs.input실패합니다. 내가 스왑 때 shallow를 위해 mount, 그것은 예상대로 작동합니다. 대부분 .. (또 하나의 문제 ESC 키를 시뮬레이션 포함)
— ffxsam을

나는 더 분명 했어야했다. 나는 다음과 같은 렌더링을 의미했습니다 render(<EditableText defaultValue="Hello" />). 귀하의 사용 사례는 제가 생각했던 것보다 더 전문적이라고 생각합니다. 입력 값을 설정하는 것만으로 메모를 처리하지만 포커스와 "변경 취소"를 처리합니다. 플 런커를 만들 수 있다면 좋을 것 입니다.
— Tyler Collier

44

로 효소 3 당신이 입력 값을 변경해야하지만 않으면 해고 할 필요가 없습니다 onChange그냥 (이 작업을 수행 할 수있는 기능 node속성이 제거되었습니다 )

wrapper.find('input').instance().value = "foo";

(즉, 제어 된 구성 요소에 대한) 소품이있는 경우 wrapper.find('input').simulate("change", { target: { value: "foo" }})호출 하는 데 사용할 수 있습니다 onChange.


7
NOTE: can only be called on a wrapper instance that is also the root instance.-airbnb.io/enzyme/docs/api/ShallowWrapper/instance.html
— davidjb

2
instance()를 통해 렌더링 된 경우 모든 자식 래퍼에서 호출 할 수 있습니다 mount.
— Vladimir Chervanev

41

알았다. (업데이트 / 개선 버전)

  it('cancels changes when user presses esc', done => {
    const wrapper = mount(<EditableText defaultValue="Hello" />);
    const input = wrapper.find('input');

    input.simulate('focus');
    input.simulate('change', { target: { value: 'Changed' } });
    input.simulate('keyDown', {
      which: 27,
      target: {
        blur() {
          // Needed since <EditableText /> calls target.blur()
          input.simulate('blur');
        },
      },
    });
    expect(input.get(0).value).to.equal('Hello');

    done();
  });

이것이 당신에게 어떻게 작용하는지 궁금합니다. 우리는 PhantomJS를 사용 mount()하고 있으며 DOM에 컴포넌트를 삽입하지 않습니다. 그래서 그들은 초점을 맞출 수 없습니다. DOM 요소를 추가하고 다음 context옵션을 사용해야합니다.mount()
— Pre101

@ Pre101 실제로 Enzyme 대신 Jest를 사용하기 시작했습니다. 추천!
— ffxsam

1
@ffxsam : input.get (0) .value 항상 표시 "정의되지 않은"
— Siddharth_Vyas

3
@Siddharth_Vyas 시도input.prop('value')
— ERSEL 케르에게

16

여기에 많은 다른 의견이 있습니다. 나를 위해 일한 유일한 것은 위의 어느 것도 사용하지 않고 input.props().value. 도움이 되었기를 바랍니다.


1
이것은 내가 입력 값을 조사 할 수있는 유일한 대답입니다.
— mojave

1
참고로 다음을 사용할 수도 있습니다. input.prop('value')소품 키의 이름을 알고있는 경우.
— Sterling Bourne

4

기본적으로 jest 및 효소 2.7.0과 함께 제공되는 create-react-app을 사용하고 있습니다.

이것은 나를 위해 일했습니다.

const wrapper = mount(<EditableText defaultValue="Hello" />);
const input = wrapper.find('input')[index]; // where index is the position of the input field of interest
input.node.value = 'Change';
input.simulate('change', input);
done();

3

위의 어느 것도 나를 위해 일하지 않았습니다. 이것이 Enzyme ^ 3.1.1에서 저에게 효과적이었습니다.

input.instance().props.onChange(({ target: { value: '19:00' } }));

다음은 컨텍스트에 대한 나머지 코드입니다.

const fakeHandleChangeValues = jest.fn();
  const fakeErrors = {
    errors: [{
      timePeriod: opHoursData[0].timePeriod,
      values: [{
        errorIndex: 2,
        errorTime: '19:00',
      }],
    }],
    state: true,
  };
const wrapper = mount(<AccessibleUI
    handleChangeValues={fakeHandleChangeValues}
    opHoursData={opHoursData}
    translations={translationsForRendering}
  />);
const input = wrapper.find('#input-2').at(0);
input.instance().props.onChange(({ target: { value: '19:00' } }));
expect(wrapper.state().error).toEqual(fakeErrors);

3

TypeScript와 함께 반응을 사용하고 있으며 다음이 나를 위해 일했습니다.

wrapper.find('input').getDOMNode<HTMLInputElement>().value = 'Hello';
wrapper.find('input').simulate('change');

값을 직접 설정

wrapper.find('input').instance().value = 'Hello'` 

나에게 컴파일 경고를 일으켰습니다.


1

이것은 효소 2.4.1을 사용하여 저에게 효과적입니다.

const wrapper = mount(<EditableText defaultValue="Hello" />);
const input = wrapper.find('input');

console.log(input.node.value);

4
Jest / enzyme을 사용하기 시작했을 때 저는 종종 console.log개체를 사용하고 필요한 것을 얻기 위해 (하위) 속성을 파헤 쳤습니다. 그렇게하면서 나는 종종 .node당신과 같은 어떤 형태로 사용하게 되었습니다. 그러나 .node공식 문서에서 언급 된 것을 본 기억 이 없습니다. 공식적으로 공개 된 API의 일부가 아니기 때문에 릴리스간에 변경 / 중단 될 수 있음을 시사합니다. 또한 종종 대안이있는 것 같습니다. 예 : input.node.value=== input.get(0).value. 따라서 .node작동 할 수 있으며 때로는 좋은 해킹을 제공 할 것이라고 생각하지만주의해서 사용합니다.
— Andrew Willems

이것은 더 이상 공개적인 방법이 아닙니다.
— Faissaloo

1

여기 내 코드입니다 ..

const input = MobileNumberComponent.find('input')
// when
input.props().onChange({target: {
   id: 'mobile-no',
   value: '1234567900'
}});
MobileNumberComponent.update()
const Footer = (loginComponent.find('Footer'))
expect(Footer.find('Buttons').props().disabled).equals(false)

내 DOM을 업데이트 componentname.update() 한 다음 길이가 10 자리 인 제출 버튼 유효성 검사 (비활성화 / 활성화)를 확인했습니다.


0

제 경우에는 ref 콜백을 사용했습니다.

  <input id="usuario" className="form-control" placeholder="Usuario"
                                                       name="usuario" type="usuario"
                                                       onKeyUp={this._validateMail.bind(this)}
                                                       onChange={()=> this._validateMail()}
                                                       ref={(val) =>{ this._username = val}}
                                                    >

가치를 얻으려면. 따라서 효소는 this._username의 값을 변경하지 않습니다.

그래서 나는 :

login.node._username.value = "mario@com.com";
    user.simulate('change');
    expect(login.state('mailValid')).toBe(true);

값을 설정하려면 change를 호출하십시오. 그리고 주장합니다.



0

누군가 어려움을 겪고 있다면 다음이 나를 위해 일한다는 것을 알았습니다.

const wrapper = mount(<NewTask {...props} />); // component under test
const textField = wrapper.find(TextField);

textField.props().onChange({ target: { value: 'New Task 2' } })
textField.simulate('change');
// wrapper.update() didn't work for me, need to find element again

console.log(wrapper.find(TextField).props()); // New Task 2

변경 이벤트에서 발생하는 일을 먼저 정의한 다음이를 시뮬레이션해야하는 것 같습니다 (데이터로 변경 이벤트를 시뮬레이션하는 대신).


0

나는 매우 간단한 방법으로 해결했습니다.

  1. props에서 값을 설정하십시오 .
  const wrapper: ShallowWrapper = shallow(<ProfileViewClass name: 'Sample Name' />);
  1. HTML 코드 :
  <input type='text' defaultValue={props.name} className='edituser-name' />
  1. 속성 액세스 에서 wrapper.find(element).props().attribute-name:
  it('should render user name', () => {
    expect(wrapper.find('.edituser-name').props().defaultValue).toContain(props.name);
  });

건배


0

Formik을 사용하고 있었고 필드 값을 변경하면서 필드를 "touched"로 표시해야했기 때문에 위의 솔루션 중 어느 것도 저에게 효과가 없었습니다. 다음 코드는 나를 위해 일했습니다.

const emailField = orderPageWrapper.find('input[name="email"]')

emailField.simulate('focus')
emailField.simulate('change', { target: { value: 'test@example.com', name: 'email' } })
emailField.simulate('blur')


-1

.simulate()어떻게 든 나를 위해 작동하지 않습니다 . node.value전화 할 필요없이 액세스하는 것만으로 작동 합니다 .simulate(). 귀하의 경우 :

const wrapper = mount(<EditableText defaultValue="Hello" />);
const input = wrapper.find('input').at(0);

// Get the value
console.log(input.node.value); // Hello

// Set the value
input.node.value = 'new value';

// Get the value
console.log(input.node.value); // new value

이것이 다른 사람들에게 도움이되기를 바랍니다!


Throws```ReactWrapper :: node에 액세스하려고 시도했습니다. 이전에는 Enzyme ReactWrapper 인스턴스의 개인 속성 이었지만 더 이상 사용되지 않으며 의존해서는 안됩니다. 대신 getElement () 메서드를 사용해보십시오. ```
— Davi Lima

2
의 효소의 최신 버전에 대한 @DaviLima 대신 .node사용한다 .instance()또는 .getDOMNode()당신이 ReactElement 또는 DOMComponent 같은 결과를 사용하는 경우, 의존한다.
— Jee Mok
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.