Enzim - <input> değerine nasıl erişilir ve ayarlanır?


91

<input>Kullanırken değere nasıl erişeceğim konusunda kafam karıştı mount. İşte testim olarak sahip olduğum şey:

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

Konsol çıktı undefined. Ancak kodu biraz değiştirirsem, işe yarıyor:

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

Tabii ki şu anda input.simulatekullandığım için hat başarısız oluyor render. Her ikisinin de düzgün çalışması için ihtiyacım var. Bunu nasıl düzeltirim?

DÜZENLE :

<EditableText />Kontrollü bir bileşen olmadığını belirtmeliyim . Ama defaultValueiçeri girdiğimde <input />, değeri belirliyor gibi görünüyor. Yukarıdaki ikinci kod bloğu değeri yazdırıyor ve aynı şekilde Chrome'daki giriş öğesini inceleyip $0.valuekonsola yazarsam beklenen değeri gösteriyor.

Yanıtlar:


100

Sanırım senin istediğin:

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

İşte kaynağım .

render()Değeri ayarlamak için herhangi bir yeri kullanmanız gerekmemelidir . Bilginize, iki farklı render()'s kullanıyorsunuz. İlk kod bloğunuzdaki Enzyme'dendir mountve wraper nesnesindeki bir yöntemdir ve findsize verir. İkincisi,% 100 net olmasa da, muhtemelen kaynaktır react-dom. Eğer Enzim kullanıyorsanız, sadece kullanmak shallowveya mountuygun olarak ve gerek yoktur renderden react-dom.


input.render()Değil react-domişlemek. İşte bu: airbnb.io/enzyme/docs/api/ShallowWrapper/render.html
ffxsam

3
Ayrıca, shallow()herhangi bir nedenle çalışmaz .. focusolay this.refs.input, başvurmaya çalışan ve başarısız olan bir yöntemi tetikler . Dışarı takas Ama shallowiçin mount, o kadar beklenir çalışır. Çoğunlukla .. (ESC anahtarını simüle
etmeyle

Daha net olmalıydım. Görünen render'ı kastetmiştim render(<EditableText defaultValue="Hello" />). Kullanım durumunuzun düşündüğümden daha özel olduğunu düşünüyorum; Görüyorum ki, sadece giriş değerini ayarlamakla, ancak odaklanmak ve "değişiklikleri iptal etmek" ile ilgili. Bir dalgıç yaratabilirseniz harika olur .
Tyler Collier

Merhaba, gibi varsayılan değerlerle ilgili sorun yaşıyorum this.state = {inputNum: 10};ve Alınan her zaman 1 olacak, ancak Beklenen 100 olarak ayarlandı input.simulate('change', { target: { value: '100' } }). Biri lütfen yardım edebilir mi?
nambk

@nambk Yeni bir soru sormak en iyisidir. Belki de bunun etrafındaki alıntılarla bir ilgisi vardır '100'. 10 ve 1 arasındaki tutarsızlıktan emin değilim.
Tyler Collier

44

İle Enzim 3 bir giriş değerini değiştirmek gerekir ancak bunu yaparsanız, ateş gerekmez onChangesadece (bunu yapabilirsiniz fonksiyonu nodeözelliği kaldırıldı ):

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

Bunun wrapper.find('input').simulate("change", { target: { value: "foo" }})için bir desteğiniz onChangevarsa (yani, kontrollü bileşenler için) çağırmak için kullanabilirsiniz .


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()aracılığıyla oluşturulmuşsa herhangi bir alt sarmalayıcıda çağrılabilir mount.
Vladimir Chervanev

41

Anladım. (güncellenmiş / geliştirilmiş versiyon)

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

Bunun sizin için nasıl çalıştığını merak ediyorum. PhantomJS kullanıyoruz ve mount()DOM'a bileşen eklemiyoruz . Yani odaklanamıyorlar. Bir DOM öğesi eklemeli ve şu contextseçeneği kullanmalıyızmount()
Pre101

@ Pre101 Aslında Enzyme yerine Jest kullanmaya başladım. Şiddetle tavsiye edilir!
ffxsam

1
@ffxsam: input.get (0) .value her zaman "tanımsız" olarak görüntülenir
Siddharth_Vyas

3
@Siddharth_Vyas deneyininput.prop('value')
Ersel Aker

16

Burada pek çok farklı görüş var. Benim için işe yarayan tek şey yukarıdakilerin hiçbiri değildi, kullanıyordu input.props().value. Umarım bu yardımcı olur.


1
Girdinin değerini sorgulamama izin veren tek cevap bu.
mojave

1
Not olarak, şunu da kullanabilirsiniz: input.prop('value')pervane anahtarınızın adını biliyorsanız.
Sterling Bourne

4

Varsayılan olarak jest ve enzim 2.7.0 ile gelen create-react-app kullanıyorum.

Bu benim için çalıştı:

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

Yukarıdakilerin hiçbiri benim için işe yaramadı. Enzyme ^ 3.1.1'de benim için işe yarayan buydu:

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

İşte bağlam için kodun geri kalanı:

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 ile react kullanıyorum ve aşağıdakiler benim için çalıştı

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

Değeri doğrudan ayarlama

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

bana bir derleme uyarısına neden oluyordu.


1

Bu, 2.4.1 enzimini kullanarak benim için çalışıyor:

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

console.log(input.node.value);

4
Jest / enzim kullanmaya başladığımda, console.logihtiyacım olanı elde etmek için genellikle bir nesne ve (alt) özellikleri araştırırdım. Bunu yaparken, seninki gibi sık sık bir şekilde kullanmaya başladım .node. Bununla birlikte, .noderesmi olarak ilan edilen API'nin resmi olarak bir parçası olmadığı için sürümler arasında değişebileceğini / bozulabileceğini öne süren resmi belgelerin herhangi birinde bahsedildiğini hatırlamıyorum . Ayrıca, genellikle alternatifler var gibi görünüyor. örneğin input.node.value=== input.get(0).value. Bu yüzden .nodeişe yarayabilir ve bazen iyi bir hack sağlayacağından şüpheleniyorum, ancak dikkatli kullanın.
Andrew Willems

Bu artık halka açık bir yöntem değil.
Faissaloo

1

işte kodum ..

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'umu componentname.update() ve ardından 10 basamak uzunluğunda gönder düğmesi doğrulamasını (devre dışı bırak / etkinleştir) ile güncelledim.


1

Herhangi birinin mücadele etmesi durumunda, aşağıdakileri benim için çalışırken buldum

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

İlk önce değişiklik olayında ne olacağını tanımlamanız ve ardından bunu simüle etmeniz gerekiyor gibi görünüyor (değişiklik olayını verilerle simüle etmek yerine)


Bu benim için çalıştı. Gerçi act () 'a onChange olayını koymak zorunda kaldım.
Pankaj

0

Benim durumumda ref geri çağırmalarını kullanıyordum,

  <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}}
                                                    >

Değeri elde etmek için. Dolayısıyla enzim bu._kullanıcı adının değerini değiştirmeyecektir.

Bu yüzden yapmak zorundaydım:

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

Değeri ayarlayabilmek için değişikliği çağırın. Ve sonra ileri sürün.


0

Bu benim için çalıştı:

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

0

Çok basit bir şekilde çözdüm:

  1. Değerleri sahne öğesinden ayarlayın :
  const wrapper: ShallowWrapper = shallow(<ProfileViewClass name: 'Sample Name' />);
  1. Html kodu :
  <input type='text' defaultValue={props.name} className='edituser-name' />
  1. Özelliğe şuradan erişinwrapper.find(element).props().attribute-name :
  it('should render user name', () => {
    expect(wrapper.find('.edituser-name').props().defaultValue).toContain(props.name);
  });

Şerefe


0

Yukarıdaki çözümlerden hiçbiri benim için işe yaramadı çünkü Formik kullanıyordum ve alan değerini değiştirmenin yanı sıra alanı "dokundu" olarak işaretlemem gerekiyordu. Aşağıdaki kod benim için çalıştı.

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()bir şekilde benim için çalışmıyor, node.valuearamaya gerek kalmadan sadece erişerek çalıştım .simulate(); Senin durumunda:

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

Umarım bu başkalarına yardımcı olur!


`` Daha önce Enzyme ReactWrapper örneklerinde özel bir özellik olan ReactWrapper :: node'a erişmeye çalışıldı, ancak artık kullanılmıyor ve güvenilmemeli. Bunun yerine getElement () yöntemini kullanmayı düşünün. `` `
Davi Lima

2
Enzim'in yeni sürümü için @DaviLima, .nodesizin yerine .instance()veya kullanmanız gerekir .getDOMNode(), sonucu bir ReactElement veya DOMComponent olarak kullanıp kullanmadığınıza bağlıdır.
Jee Mok
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.