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.