`getByRole` can't find the name of the appropriate textbox
Asked Answered
R

3

6

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.

Return answered 17/3, 2021 at 11:40 Comment(0)
H
2

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.

Hippolytus answered 30/10, 2021 at 1:49 Comment(1)
the role for a textarea is not textarea, but textbox :/ developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/…Eades
C
1

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,
  }}
/>
Crist answered 22/11, 2021 at 23:43 Comment(0)
H
0

I think, your textarea has name=body, and you're looking for name=Your Comment. Try to use body instead.

Herschel answered 17/3, 2021 at 11:49 Comment(1)
But when I search for input author I do almost exactly the same : let input = screen.getByRole("textbox", { name: "Your Name" }); And it finds the correct inputReturn

© 2022 - 2024 — McMap. All rights reserved.