Enzyme - Cách truy cập và đặt giá trị <input>?


90

Tôi bối rối về cách truy cập <input>giá trị khi sử dụng mount. Đây là những gì tôi nhận được làm bài kiểm tra của mình:

  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();
  });

Bàn điều khiển in ra undefined. Nhưng nếu tôi sửa đổi một chút mã, nó hoạt động:

  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();
  });

Tất nhiên, ngoại trừ input.simulateđường dây bị lỗi vì tôi đang sử dụng renderbây giờ. Tôi cần cả hai để hoạt động bình thường. Làm cách nào để sửa lỗi này?

CHỈNH SỬA :

Tôi nên đề cập, <EditableText />không phải là một thành phần được kiểm soát. Nhưng khi tôi chuyển defaultValuevào <input />, nó dường như đã đặt giá trị. Khối mã thứ hai ở trên không in ra giá trị và tương tự như vậy nếu tôi kiểm tra phần tử đầu vào trong Chrome và nhập $0.valuevào bảng điều khiển, nó sẽ hiển thị giá trị mong đợi.

Câu trả lời:


99

Tôi nghĩ những gì bạn muốn là:

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

Đây là nguồn của tôi .

Bạn không cần phải sử dụng render()bất kỳ đâu để đặt giá trị. Và chỉ FYI, bạn đang sử dụng hai cái khác nhau render(). Một trong khối mã đầu tiên của bạn là từ Enzyme, và là một phương thức trên đối tượng wraper mountfindcung cấp cho bạn. Cái thứ hai, mặc dù nó không rõ ràng 100%, có lẽ là cái từ react-dom. Nếu bạn đang sử dụng Enzyme, chỉ cần sử dụng shallowhoặc mountkhi thích hợp và không cần rendertừ react-dom.


Không input.render()được react-domkết xuất. Đó là cái này: airbnb.io/enzyme/docs/api/ShallowWrapper/render.html
ffxsam

3
Ngoài ra, shallow()không hoạt động vì một số lý do .. focussự kiện kích hoạt một phương thức cố gắng tham chiếu this.refs.input, nhưng không thành công. Nhưng khi tôi đổi shallowlấy mount, nó hoạt động như mong đợi. Chủ yếu .. (một vấn đề nhiều hơn với mô phỏng phím ESC)
ffxsam

Tôi cần phải có được rõ ràng hơn. Ý tôi là kết xuất trông như thế nào render(<EditableText defaultValue="Hello" />). Tôi nghĩ rằng trường hợp sử dụng của bạn chuyên biệt hơn tôi nghĩ; Tôi thấy nó đề cập đến việc đặt giá trị đầu vào nhưng với tiêu điểm và "hủy thay đổi". Sẽ thật tuyệt nếu bạn có thể tạo ra một chiếc plunker .
Tyler Collier

44

Với Enzyme 3 , nếu bạn cần thay đổi giá trị đầu vào nhưng không cần kích onChangehoạt hàm, bạn có thể thực hiện việc này (thuộc nodetính đã bị xóa ):

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

Bạn có thể sử dụng wrapper.find('input').simulate("change", { target: { value: "foo" }})để gọi onChangenếu bạn có chỗ dựa cho điều đó (tức là đối với các thành phần được kiểm soát).


7
NOTE: can only be called on a wrapper instance that is also the root instance.- từ tài liệu tại airbnb.io/enzyme/docs/api/ShallowWrapper/instance.html
davidjb

2
instance()có thể được gọi trên bất kỳ trình bao bọc con nào nếu nó được hiển thị qua mount.
Vladimir Chervanev

41

Hiểu rồi. (phiên bản cập nhật / cải tiến)

  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();
  });

Tò mò làm thế nào điều này làm việc cho bạn. Chúng tôi đang sử dụng PhantomJS và mount()không chèn các thành phần vào DOM. Vì vậy, họ không thể nhận được tiêu điểm. Chúng tôi phải thêm một phần tử DOM và sử dụng contexttùy chọn chomount()
Pre101

@ Pre101 Tôi thực sự đã bắt đầu sử dụng Jest thay vì Enzyme. Rất khuyến khích!
ffxsam

1
@ffxsam: input.get (0) .value luôn hiển thị "không xác định"
Siddharth_Vyas

3
@Siddharth_Vyas thửinput.prop('value')
Ersel Aker

16

Rất nhiều ý kiến ​​khác nhau ở đây. Điều duy nhất làm việc cho tôi không phải là điều ở trên, nó đang sử dụng input.props().value. Tôi hy vọng rằng sẽ giúp.


1
Đây là câu trả lời duy nhất cho phép tôi thẩm vấn giá trị của đầu vào.
mojave

1
Lưu ý, bạn cũng có thể sử dụng: input.prop('value')nếu bạn biết tên của khóa chống đỡ của mình.
Sterling Bourne

4

Tôi đang sử dụng ứng dụng tạo-phản ứng đi kèm với jest và enzyme 2.7.0 theo mặc định.

Điều này đã làm việc cho tôi:

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

Không có điều nào ở trên phù hợp với tôi. Đây là những gì làm việc cho tôi trên Enzyme ^ 3.1.1:

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

Đây là phần còn lại của mã cho ngữ cảnh:

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

Tôi đang sử dụng phản ứng với TypeScript và điều sau đây phù hợp với tôi

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

Đặt giá trị trực tiếp

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

đã gây ra cho tôi một cảnh báo biên dịch.


1

Điều này hoạt động đối với tôi bằng cách sử dụng enzyme 2.4.1:

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

console.log(input.node.value);

4
Khi tôi bắt đầu sử dụng Jest / enzyme, tôi thường tìm console.logmột đối tượng và tìm hiểu các thuộc tính (phụ) để lấy thứ tôi cần. Làm như vậy, tôi thường sử dụng .nodeở một số hình thức, như bạn đã làm. Tuy nhiên, tôi không nhớ mình đã thấy .nodeđược đề cập trong bất kỳ tài liệu chính thức nào, cho thấy nó có thể thay đổi / ngắt giữa các bản phát hành vì nó không phải là một phần chính thức của API được quảng cáo công khai. Ngoài ra, dường như thường có các lựa chọn thay thế. ví dụ: input.node.value=== input.get(0).value. Vì vậy, .nodecó thể hoạt động, và tôi nghi ngờ rằng đôi khi nó sẽ cung cấp một bản hack tốt, nhưng hãy sử dụng một cách thận trọng.
Andrew Willems

Đây không còn là một phương pháp công khai.
Faissaloo

1

đây là mã của tôi ..

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)

Tôi đã cập nhật DOM của mình bằng componentname.update() Và sau đó kiểm tra xác thực nút gửi (tắt / bật) với độ dài 10 chữ số.


0

Trong trường hợp của tôi, tôi đã sử dụng lệnh gọi lại 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}}
                                                    >

Để có được giá trị. Vì vậy, enzyme sẽ không thay đổi giá trị của this._username.

Vì vậy, tôi phải:

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

Để có thể thiết lập giá trị sau đó gọi thay đổi. Và sau đó khẳng định.


0

Điều này đã làm việc cho tôi:

let wrapped = mount(<Component />);
expect(wrapped.find("input").get(0).props.value).toEqual("something");

0

Trong trường hợp bất kỳ ai đang gặp khó khăn, tôi thấy những điều sau đây phù hợp với tôi

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

Có vẻ như bạn cần xác định điều gì xảy ra trong sự kiện thay đổi trước rồi mô phỏng nó (thay vì mô phỏng sự kiện thay đổi bằng dữ liệu)


0

Tôi đã giải quyết theo một cách rất đơn giản:

  1. Đặt giá trị từ các đạo cụ :
  const wrapper: ShallowWrapper = shallow(<ProfileViewClass name: 'Sample Name' />);
  1. Mã html :
  <input type='text' defaultValue={props.name} className='edituser-name' />
  1. Truy cập thuộc tính từ wrapper.find(element).props().attribute-name:
  it('should render user name', () => {
    expect(wrapper.find('.edituser-name').props().defaultValue).toContain(props.name);
  });

Chúc mừng


0

Không có giải pháp nào ở trên phù hợp với tôi vì tôi đang sử dụng Formik và tôi cần đánh dấu trường "đã chạm" cùng với việc thay đổi giá trị trường. Mã sau làm việc cho tôi.

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()không làm việc cho tôi bằng cách nào đó, tôi đã làm cho nó hoạt động chỉ với việc truy cập node.valuemà không cần gọi .simulate(); trong trường hợp của bạn:

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

Hy vọng điều này sẽ giúp ích cho những người khác!


Ném nút `` Đã cố gắng truy cập nút ReactWrapper ::, trước đây là thuộc tính riêng tư trên các phiên bản Enzyme ReactWrapper, nhưng không còn và không nên dựa vào. Thay vào đó, hãy xem xét sử dụng phương thức getElement (). ``
Davi Lima

2
@DaviLima cho phiên bản Enzyme mới hơn, thay vì .nodebạn nên sử dụng .instance()hoặc .getDOMNode(), tùy thuộc vào việc bạn sử dụng kết quả là ReactElement hay DOMComponent.
Jee Mok
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.