Reputation: 899
Here is the test for the :
it("changes the state when body input is changed", () => {
render(<CommentForm />)
// let input = screen.getByLabelText("Your Name");
let input = screen.getByRole("textbox", { name: "Your Comment" });
fireEvent.change(input, { target: { value: "MyComment" } });
expect(input.value).toEqual("MyComment");
});
With the commented line it works (when I search with getByLabelText
). Here is what I am getting when I try to find it with getByRole
:
Unable to find an accessible element with the role "textbox" and name "Your Comment"
Here are the accessible roles:
document:
Name "":
<body />
--------------------------------------------------
generic:
Name "":
<div />
Name "":
<div
class="input-group"
/>
Name "":
<div
class="input-group"
/>
--------------------------------------------------
heading:
Name "Post a Comment":
<h2 />
--------------------------------------------------
textbox:
Name "Your Name":
<input
id="author-name"
name="author"
type="text"
value=""
/>
Name "":
<textarea
cols="30"
id="body"
name="body"
rows="10"
/>
So it seems like the name is empty but I am not sure why that is.
And here is the actual component:
import React from "react";
import useInput from "../hooks/useInput";
const CommentForm = ({ onSubmit }) => {
const { value: author, reset: resetAuthor, bind: bindAuthor } = useInput("");
const { value: body, reset: resetBody, bind: bindBody } = useInput("");
const handleSubmit = (e) => {
e.preventDefault();
onSubmit({ author, body }, resetInputs);
};
const resetInputs = () => {
resetAuthor();
resetBody();
};
return (
<form onSubmit={handleSubmit}>
<h2>Post a Comment</h2>
<div className="input-group">
<label htmlFor="author-name">Your Name</label>
<input id="author-name" type="text" name="author" {...bindAuthor} />
</div>
<div className="input-group">
<label htmlFor="body">Your Comment</label>
<textarea
id="body"
name="body"
cols="30"
rows="10"
{...bindBody}
></textarea>
</div>
<button type="submit">Submit</button>
</form>
);
};
export default CommentForm;
Can anyone see the issue here. I am sure it should work and I don't see any reason why the author input can be grabbed with getByRole
and name but this one can't.
Upvotes: 7
Views: 18909
Reputation: 35
I came across this problem when using a React Hook Form Controller for a Material UI TextField. Even though my TextField element had a label prop, no aria-label
value was present in the HTML until I added the inputProps={{ "aria-label": "Email" }}
prop to the TextField component.
Note: the aria-label is the value that the getByRole "name" actually refers to in this case. See docs for details.
<Controller
control={control}
defaultValue=""
id="email"
name="email"
render={({ onChange, ref }) => (
<TextField
autoComplete="email"
className={classes.textField}
error={Boolean(errors.email)}
fullWidth
helperText={errors.email && errors.email.message}
inputProps={{ "aria-label": "Email" }}
inputRef={ref}
label="Email"
onChange={onChange}
/>
)}
rules={{
pattern: {
message: "invalid email address",
value: EMAIL_REGEX,
},
required: true,
}}
/>
Upvotes: 1
Reputation: 1586
Your use of <label htmlFor>
is incorrect. Because you've given htmlFor
, id
and body
the same values the DOM is getting confused and assigning the label content ("Your Comment") as the name. It's working with author by accident.
So:
<label htmlFor="author-name">Your Name</label>
<input id="author-name" type="text" name="author" />
Should be able to be checked with:
screen.getByRole('textbox', {name: author})
For the textarea
if you do:
<label htmlFor="body">Your Comment</label>
<textarea
id="body"
name="bodyInput"
>
Then:
screen.getByRole('textarea', {name: body})
Should give you the result you're looking for.
Notice in both cases I'm checking the element's name
value in the element where id
matches the value of htmlFor
. I am not checking the value of the <label>
text itself.
Upvotes: 3
Reputation:
I think, your textarea
has name=body
, and you're looking for name=Your Comment
. Try to use body
instead.
Upvotes: 0