Estoy tratando de escribir una prueba simple para verificar que se llamó a un accesorio cuando el usuario interactúa con un par de botones. Aquí está mi prueba:
it('submits the name on save', async () => { const name = 'Some name' const updatedName = 'New name' const onSubmit = jest.fn() render( <EditableName name={name} onSubmit={onSubmit} /> ) act(() => { fireEvent.click(getByText('Edit')) fireEvent.change(getByRole('input'), { target: { value: updatedName } }) fireEvent.click(getByText('Save')) }) expect(onSubmit).toBeCalledTimes(1) })Resultado:
● EditableName › submits the name on save expect(jest.fn()).toBeCalledTimes(expected) Expected number of calls: 1 Received number of calls: 0 Cuando hago console.log para ver si se está alcanzando la línea que llama a onSubmit , puedo ver que sí.
Sospecho que el problema es que la función onSubmit que espero es una instancia diferente de la función en el momento en que .toBeCalledTimes() . Debido a que los tres eventos que estoy disparando hacen que el componente se vuelva a renderizar.
¿Cómo puedo asegurarme de que la función que estoy pasando como accesorio en la prueba es la misma que se está llamando? ¿Necesito usar spyOn ? ¿Si es así, cómo?
¡Gracias por adelantado!
Editar: Aquí está el ejemplo de código mínimo del componente:
import React, { useState } from "react"; import { Box, Button, TextField, Typography } from "@material-ui/core"; const EditableName = ({ name, onSubmit }) => { const [editing, setEditing] = useState(false); const [value, setValue] = useState(name); const handleSubmit = () => { onSubmit({ name: value }); }; const handleToggleEditMode = () => { if (editing) { setEditing(false); setValue(name); } else { setEditing(true); } }; if (!editing) { return ( <> <Typography display="inline" variant="h5" component="h1"> {name} </Typography> <Button onClick={handleToggleEditMode}> Edit </Button> </> ); } return ( <> <TextField name="name" variant="outlined" fullWidth size="small" label="Subsidy name" value={value} onChange={(e) => setValue(e.target.value)} inputProps={{ role: "input" }} /> <Button onClick={handleSubmit}>Save</Button> </> ); }; export default EditableName;Creo que necesita separar los eventos, y act está integrado en RTL, por lo que debe usar await waitFor en su lugar:
await waitFor(() => { fireEvent.click(getByText('Edit')) }); //should probably assert changes here await waitFor(() => { fireEvent.change(getByRole('input'), { target: { value: updatedName } }) }); //should probably assert changes here await waitFor(() => { fireEvent.click(getByText('Save')) }) expect(onSubmit).toBeCalledTimes(1)