Skip to content

Descriptively assert that a form input/select/textarea has a given value #60

Closed
@gnapse

Description

@gnapse

The problem

<select> elements, unlike input elements, do not have a value attribute. So there's easy no natural way to assert that a select element has a certain option selected. One would have to traverse through the options to see which one is selected.

To make it even worse, React makes it look like so, to the point that I got confused myself recently, when I spent more minutes that I would've liked trying to figure out why the following test (using react-testing-library) did not pass:

const { getByTitle } = render(
  <select title="Client status" value="archived">
    <option value="active">Active</option>
    <option value="archived">Archived</option>
    <option value="pending">Pending</option>
  </select>
);

expect(getByTitle('Client status')).toHaveAttribute('value', 'archived')

And to continue to make it even worse, the overall task may become more complex if using options grouped in <optgroup>s, or with multi-select elements.

Describe the feature you'd like

I started this issue thinking of suggesting a specific matcher to check a selected option in select elements. But while describing all of the above, I realize that it may be better to provide some generic way to check the value of form elements, regardless of them being inputs, textareas or selects (are there any other ones?).

Suggested implementation:

It could be providing assertions to work at the actual form input element level:

expect(userInputElement).toHaveValue('janedoe');
expect(passwordInputElement).toHaveValue('12345678');

or even at the form element level (identifying an input/select/textarea element by its name attribute):

expect(formElement).toHaveValue('username', 'janedoe');
expect(formElement).toHaveValue('password', '12345678');

It could be both use cases with the same matcher! And it could be created so that it would understand inputs, selects and textures (which are also different, their value is their child text content).

It could even be so that <select multiple> elements' values are arrays, and users could check at once the entire multiple selection (and maybe even part of it too??)

Describe alternatives you've considered:

select elements probably have some property at the dom level to check their value, instead of it being an attribute. I did not google for it, and do not have it at the top of my head, but if so, then expect(selectElement.value).toEqual(...) could help, but still it's not a generic solution for all kinds of form elements (or is it?)

dom-testing-library recently added the ability to getBySelectText, that allows users to select a select (pun not intended) by the text content of the option element within that select that is currently selected. This certainly helps, but it still leaves a weird not-so-expressive way to assert that a given select has a certain value selected:

expect(getByLabel('Client status')).toBe(getBySelectText('Archived'))

And even then, what happens if there are two selects that happen to have an option selected, both with the same text "Archived"?

And still this only addresses the problem with select elements.

Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is neededneeds discussionWe need to discuss this to come up with a good solution

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions