Search code examples
javascriptreactjsaccessibilityreact-testing-library

What is a role of input with type number


I am using react testing library and by its conventions, elements should be accessed by getByRole.

When I had input type="text" the role was textarea which was fine.

Now I have input with type="number" and the error message suggests I use spinbutton as the role which works but it doesn't make sense to me.

Is there a different role for input with number type?


Solution

  • As per MDN on <input type="number">:

    The implicit role for the element is spinbutton.

    So as long as you didn't change the role by means of a role attribute, this is the correct role to use in getByRole('spinbutton').

    An input number is like a counter, so it is spinning its values up and down by clicking in the spin buttons on the right side or the keyboard arrows, (even its pseudo elements are ::-webkit-inner-spin-button, ::-webkit-outer-spin-button).

    If this is surprising to you, that input type might not be the right choice for the form control. The documentation reads further:

    If spinbutton is not an important feature for your form control, consider not using type="number". Instead, use inputmode="numeric" along with a pattern attribute that limits the characters to numbers and associated characters.

    The number input has several accessibility and usability issues when used for anything that is not a floating point number.

    Update (based on OP comment)

    So would userEvent.type work on it since it is a spinbutton?

    Yes it will work, here is a sandbox with a basic example

    Codesandbox Demo


    import { render, waitFor } from "@testing-library/react";
    import userEvent from "@testing-library/user-event";
    import "@testing-library/jest-dom";
    
    it("should type a number in input", () => {
      const { getByRole } = render(<input type="number" />);
      const input = getByRole("spinbutton");
      userEvent.type(input, "123456");
      waitFor(() => expect(input).toHaveValue("123456"));
    });