I'm trying to do a test, in which when changing the input, I have to read the useMemo and change the disabled of my button, the userEvent is not making this change, has anyone gone through this?
I'm going to put part of my source code here, where the component and the test script are.
<>
<input
data-testid="ipt-email"
value={form.email}
onChange={(e) => {
setForm({ ...form, email: e.target.value });
}}
/>
<button data-testid="submit-sendUser" disabled={isDisabled}>
OK
</button>
</>
This is my hook
const isDisabled = useMemo(() => {
const { email } = form;
if (!email.length) return true
return false;
}, [form]);
Right after that is my unit test, where I write to the input and wait for the state to change
import userEvent from "@testing-library/user-event";
it("Should enable button when form is valid", async () => {
const wrapper = render(<MyComponent />);
const getEmail = wrapper.getByTestId("ipt-name");
await userEvent.type(getEmail, '[email protected]');
const getBtnSubmit = wrapper.getByTestId("submit-sendUser");
console.log(wrapper.container.innerHTML);
expect(getBtnSubmit).not.toBeDisabled();
});
I can't make the input change reflect in the button hook
CodePudding user response:
The combination of fireEvents and forced move to the "next frame" worked for me
const tick = () => {
return new Promise((resolve) => {
setTimeout(resolve, 0);
});
};
// async test
fireEvent.change(getEmail, {target: {value: '[email protected]'}})
await tick();
expect(getBtnSubmit).not.toBeDisabled();
CodePudding user response:
Need to wait for changes to occur after the action
await waitFor(() => expect(getBtnSubmit).not.toBeDisabled())
moving code inside the handler applied to useEffect, but I feel its better to handle the validation inside the handler.
Hope it helps
CodePudding user response:
In your constant getEmail you get a component with a data-testid='ipt-name' instead of 'ipt-email'. The code below works for me :
my test :
import { render, screen, waitFor } from '@testing-library/react';
import App from './App';
import userEvent from '@testing-library/user-event';
it("Should enable button when form is valid", async () => {
render(<App />);
expect(screen.getByTestId("submit-sendUser")).toBeDisabled();
const getEmail = screen.getByTestId("ipt-email");
userEvent.type(getEmail, '[email protected]');
await waitFor(() => expect(screen.getByTestId("submit-sendUser")).not.toBeDisabled());
});
my component :
import React, { useMemo, useState } from "react";
export const App = () => {
const [form, setForm] = useState({ email: '' });
const isDisabled = useMemo(() => {
const { email } = form;
if (!email || !email.length) return true;
return false;
}, [form]);
return (
<div>
<input
data-testid="ipt-email"
value={form.email}
onChange={(e) => {
setForm({ ...form, email: e.target.value });
}}
/>
<button data-testid="submit-sendUser" disabled={isDisabled}>
OK
</button>
</div>
);
};
export default App;