酶-如何访问和设置<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在控制台中键入,它将显示期望的值。

Answers:


99

我认为您想要的是:

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

这是我的消息来源

您无需在render()任何地方使用它来设置值。仅供参考,您使用的是两种不同render()的。第一个代码块中的一个来自Enzyme,它是包装对象上的一种方法mountfind为您提供。尽管不是100%清晰,但第二个可能是中的一个react-dom。如果您使用的是酶,只需使用shallowmount适当的话,就不需要renderfrom react-dom


input.render()react-dom渲染。就是这样:airbnb.io/enzyme/docs/api/ShallowWrapper/render.html
ffxsam

3
同样,shallow()由于某种原因也不起作用。.focus事件触发一个尝试引用的方法this.refs.input,该方法失败。但是,当我换出shallowmount,它按预期工作。通常..(模拟ESC键还有一个问题)
ffxsam

我应该更清楚了。我的意思是看起来像的渲染render(<EditableText defaultValue="Hello" />)。我认为您的用例比我想象的更专业;我看到它只是设置输入值而已,但是具有焦点和“取消更改”。如果您可以制造一个塞子,那就太好了
泰勒·科利尔

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
弗拉基米尔·切尔万涅夫(Fladimir 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,2016年

@ Pre101我实际上开始使用Jest而不是Enzyme。强烈推荐!
ffxsam

1
@ffxsam:input.get(0).value始终显示“未定义”
Siddharth_Vyas

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

16

这里有很多不同的意见。唯一对我有用的是上述所有方法,而没有使用input.props().value。希望对您有所帮助。


1
这是唯一允许我询问输入值的答案。
mojave

1
值得注意的是,您还可以使用:input.prop('value')如果您知道道具钥匙的名称。
Sterling Bourne

4

我正在使用默认情况下带有笑话和酶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

以上都不对我有用。这是我对酶^ 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 /酶时,我经常会使用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

这对我有用:

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

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,并且需要在更改字段值的同时将字段标记为“已触摸”。以下代码为我工作。

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

希望这对其他人有帮助!


引发```尝试访问ReactWrapper :: node,该节点以前是Enzyme ReactWrapper实例的私有属性,但不再使用,因此不应依赖。考虑改用getElement()方法。```
Davi Lima

2
@DaviLima用于较新版本的Enzyme,而不是.node应该使用.instance().getDOMNode(),这取决于您将结果用作ReactElement还是DOMComponent。
Jee Mok
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.