Description
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 input
s, textarea
s or select
s (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?