Enzima: ¿Cómo acceder y configurar el valor <input>?


90

Estoy confundido acerca de cómo acceder al <input>valor cuando lo uso mount. Esto es lo que tengo como prueba:

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

Se imprime la consola undefined. Pero si modifico ligeramente el código, funciona:

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

Excepto, por supuesto, que la input.simulatelínea falla ya que la estoy usando renderahora. Necesito que ambos funcionen correctamente. ¿Cómo puedo solucionar esto?

EDITAR :

Debo mencionar <EditableText />que no es un componente controlado. Pero cuando paso defaultValueen <input />, al parecer para ajustar el valor. El segundo bloque de código anterior imprime el valor y, de la misma manera, si inspecciono el elemento de entrada en Chrome y escribo $0.valueen la consola, muestra el valor esperado.

Respuestas:


99

Creo que lo que quieres es:

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

Aquí está mi fuente .

No debería necesitar usar render()ningún lugar para establecer el valor. Y solo para su información, está utilizando dos diferentes render(). El que está en su primer bloque de código es de Enzyme, y es un método en el objeto envoltorio mounty le findproporciona. El segundo, aunque no está 100% claro, es probablemente el de react-dom. Si está utilizando la enzima, sólo tiene que utilizar shallowo mountsegún el caso y no hay necesidad de renderpartir react-dom.


No input.render()es react-domrender. Es esto: airbnb.io/enzyme/docs/api/ShallowWrapper/render.html
ffxsam

3
Además, shallow()no funciona por alguna razón ... el focusevento activa un método que intenta hacer referencia this.refs.input, que falla. Pero cuando intercambiar shallowpara mount, funciona como se esperaba. Principalmente ... (un problema más con la simulación de la tecla ESC)
ffxsam

Debería haber sido más claro. Me refiero al render que parece render(<EditableText defaultValue="Hello" />). Creo que su caso de uso es más especializado de lo que pensaba; Veo que se ocupa de la nota solo con establecer el valor de entrada pero con el enfoque y "cancelar cambios". Sería genial si pudieras crear un plunker .
Tyler Collier

44

Con la Enzima 3 , si necesita cambiar un valor de entrada pero no necesita onChangeactivar la función, simplemente puede hacer esto (la nodepropiedad ha sido eliminada ):

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

Puede usar wrapper.find('input').simulate("change", { target: { value: "foo" }})para invocar onChangesi tiene un accesorio para eso (es decir, para componentes controlados).


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

2
instance()se puede llamar en cualquier contenedor secundario si se procesó a través de mount.
Vladimir Chervanev

41

Entendido. (versión actualizada / mejorada)

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

Curioso cómo funciona esto para ti. Estamos usando PhantomJS y mount()no inserta componentes en el DOM. Entonces, no pueden recibir atención. Tenemos que agregar un elemento DOM y usar la contextopción paramount()
Pre101

@ Pre101 De hecho, comencé a usar Jest en lugar de Enzyme. ¡Muy recomendable!
ffxsam

1
@ffxsam: input.get (0) .value siempre muestra "undefined"
Siddharth_Vyas

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

16

Hay muchas opiniones diferentes aquí. Lo único que funcionó para mí fue nada de lo anterior, estaba usando input.props().value. Espero que eso ayude.


1
Esta es la única respuesta que me permitió interrogar el valor de la entrada.
Mojave

1
Cabe destacar que también puede usar: input.prop('value')si conoce el nombre de su clave de apoyo.
Sterling Bourne

4

Estoy usando create-react-app que viene con jest por defecto y enzima 2.7.0.

Esto funcionó para mí:

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

Ninguno de los anteriores funcionó para mí. Esto es lo que funcionó para mí en Enzyme ^ 3.1.1:

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

Aquí está el resto del código para el contexto:

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

Estoy usando react con TypeScript y lo siguiente funcionó para mí

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

Establecer el valor directamente

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

me estaba provocando una advertencia de compilación.


1

Esto me funciona usando la enzima 2.4.1:

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

console.log(input.node.value);

4
Cuando comencé a usar Jest / enzima, a menudo console.logbuscaba un objeto y buscaba (sub) propiedades para obtener lo que necesitaba. Al hacerlo, a menudo terminé usando .nodede alguna forma, como tú. Sin embargo, no recuerdo haber .nodesido mencionado en ninguna de la documentación oficial, lo que sugiere que podría cambiar / interrumpirse entre lanzamientos, ya que no forma parte oficialmente de la API anunciada públicamente. Además, a menudo parece haber alternativas. por ejemplo input.node.value=== input.get(0).value. Entonces, .nodepodría funcionar, y sospecho que a veces proporcionará un buen truco, pero utilícelo con precaución.
Andrew Willems

Este ya no es un método público.
Faissaloo

1

aquí está mi código ..

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)

He actualizado mi DOM con componentname.update() Y luego verifiqué la validación del botón de envío (deshabilitar / habilitar) con una longitud de 10 dígitos.


0

En mi caso, estaba usando devoluciones de llamada de referencia,

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

Para obtener el valor. Así que la enzima no cambiará el valor de this._username.

Entonces tuve que:

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

Para poder establecer el valor, llame al cambio. Y luego afirmar.


0

Esto funcionó para mí:

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

0

En caso de que alguien tenga dificultades, encontré lo siguiente que me funciona

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

Parece que primero debe definir lo que sucede en el evento de cambio y luego simularlo (en lugar de simular el evento de cambio con datos)


0

Resolví de una manera muy simple:

  1. Establezca el valor de los accesorios :
  const wrapper: ShallowWrapper = shallow(<ProfileViewClass name: 'Sample Name' />);
  1. Código HTML :
  <input type='text' defaultValue={props.name} className='edituser-name' />
  1. Acceda al atributo desde wrapper.find(element).props().attribute-name:
  it('should render user name', () => {
    expect(wrapper.find('.edituser-name').props().defaultValue).toContain(props.name);
  });

Salud


0

Ninguna de las soluciones anteriores funcionó para mí porque estaba usando Formik y necesitaba marcar el campo como "tocado" junto con cambiar el valor del campo. El siguiente código funcionó para mí.

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()no funciona para mí de alguna manera, lo hice funcionar con solo acceder node.valuesin necesidad de llamar .simulate(); en tu caso:

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

¡Espero que esto ayude a los demás!


Lanza `` `Intentó acceder a ReactWrapper :: node, que anteriormente era una propiedad privada en las instancias de Enzyme ReactWrapper, pero ya no lo es y no se debe confiar en él. Considere utilizar el método getElement () en su lugar. ``
Davi Lima

2
@DaviLima para la versión más reciente de Enzyme, en lugar de .nodedebe usar .instance()o .getDOMNode(), depende de si usó el resultado como ReactElement o DOMComponent.
Jee Mok
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.