🙂 Estoy aprendiendo a probar en React, pero fireEvent no cambia el valor de mi entrada. Desafortunadamente, no sé por qué.
Estoy renderizando el componente BuyPlace. En este componente, tengo un formulario que tiene componentes de entrada (estos componentes simplemente se etiquetan con entrada y estoy pasando accesorios a estos componentes en el formulario).
En screen.debug() puedo ver que mis componentes se representan correctamente con este formulario y todas estas entradas.
Además, mi entrada se detecta correctamente en mi prueba, verifiqué esto.
Esta es mi prueba:
test("should change input value", async () => { render( <HashRouter> <UserContext.Provider value={{ user: true }}> <BuyPlace /> </UserContext.Provider> </HashRouter> ); const nameInputEl = screen.getByPlaceholderText("Podaj własną nazwę"); fireEvent.change(nameInputEl, { target: { value: "Michał" }, }); await waitFor(() => { expect(nameInputEl.value).toBe("Michał"); }); });La prueba no está pasando. Por supuesto, mi aplicación funciona correctamente, pero en la prueba no funciona.
Esto es handleInputChange en mi componente:
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement> | React.ChangeEvent<HTMLTextAreaElement>) => { setInputValues((prevValues) => { return { ...prevValues, [e.target.name]: e.target.value, } }); };Todas las soluciones que encontré no funcionan ... Mi valor en la entrada siempre es una cadena vacía. ¿Puede alguien ayudarme con esto? Quiero aprender a escribir buenas pruebas, pero no sé dónde está el problema.
EDITAR Vi algo interesante en screen.debug().
Mi entrada en la prueba se representa sin el atributo onchange, ¿esto es normal en las pruebas? Mira esto:
<input id="name" name="name" placeholder="Podaj własną nazwę" type="text" value="" />En mi componente principal representado, tengo handleInputChange y esta función pasa a los componentes de entrada. En vivo, todo funciona, pero en la prueba no ... ¿Quizás es por eso que fireEvent no funciona?
Pero, ¿por qué, en la prueba, mi entrada no tiene el atributo onchange?
EDICIÓN 2 SOLUCIÓN
¡Guau, después de 3 días encontré dónde estaba el problema!
El problema estaba en la función setState que cambia los valores. Yo Tuve:
const myValues = (object with values); setState((previousValues) => { ...previousValues, [e.target.name]: e.target.value })Pero después de cambiar esto:
setState({ ...myValues, [e.target.name]: e.target.value })Mi prueba está pasando. Por lo tanto, no puedo usar la devolución de llamada de estado anterior en setState; es por eso que mi prueba fue incorrecta. ¿Pero por qué? ¡Esta es una pregunta para mí!
Se recomienda usar userEvent sobre fireEvent . Especialmente si está utilizando Material-UI , ya que ha habido problemas con el uso de fireEvent en lugar userEvent
Nota probando la documentación de la biblioteca
La mayoría de los proyectos tienen algunos casos de uso para fireEvent, pero la mayoría de las veces probablemente debería usar @testing-library/user-event.
En lugar de fireEvent.change , harías algo como tal
userEvent.type(nameInputEl, 'Michal');Espero que sepas que esto no devuelve nada todavía.
esta pieza es de tu pregunta;
setState((previousValues) => { ...previousValues, [e.target.name]: e.target.value })necesitas envolverlo como se muestra a continuación;
setState((previousValues) => ({ ...previousValues, [e.target.name]: e.target.value }))