qunit-dom icon indicating copy to clipboard operation
qunit-dom copied to clipboard

containingText selection constraint

Open ef4 opened this issue 3 years ago • 5 comments

This adds the ability to restrict your selection to the first element that contains the given text.

assert.dom('button').containingText('submit').hasAttribute('disabled');

This gives a reasonable replacement for the never-standardized :contains() selector that was implemented in jQuery. I have been missing it.

ef4 avatar Oct 29 '20 05:10 ef4

Hey @ef4 thank you for taking the time to submit this PR, would it be possible to add some use-cases here to see what containingText aims to resolve.

From the example assertions in the tests the same outcome can be achieved by looking up the classes on the elements and using includesText.

patsy-issa avatar Oct 29 '20 10:10 patsy-issa

Locating an element via its class and then asserting its text is very different from locating an element via its text and then asserting its class.

Consider an example like this:

assert.dom('button').containingText('Save Your Changes').hasAttribute('disabled');

You might try to reverse the semantics:

assert.dom('button[disabled]').includesText('Save Your Changes');

But that will fail as soon as you have more than one disabled button. Instead you may be forced to add a test-specific attribute to your template, in order to select the button you really want. containsText lets you avoid that, by picking the button you want based on its text.

ef4 avatar Oct 29 '20 10:10 ef4

From a personal standpoint I would prefer to encourage people to use descriptive identifiers/data-attributes that are stripped away from production, in order to decouple the tests from the html elements and be sure we are asserting against the element expected, i.e:

assert.dom('[data-test-save-changes]').hasAttribute('disabled');

Another concern would be that we might cause confusion between containingText and includesText's alias containsText.

What are your thoughts @Turbo87 @scalvert ?

patsy-issa avatar Oct 29 '20 11:10 patsy-issa

IMO it very much depends which semantics you're trying to encode in your particular test.

If you're trying to always target an exact component implementation, sure, add a dedicated selector.

But sometimes you're trying to model the user's behavior. And users don't pick things based on selectors. They pick them based on text.

ef4 avatar Oct 29 '20 11:10 ef4

whoops, sorry for the long radio silence here! 🙊

I tend to agree with @patsy-issa though that using test selectors or regular selectors is most of the time sufficient, and if it isn't then qunit-dom already allows people to pass in raw DOM nodes.

The only disadvantage that you get from passing in raw DOM nodes is that the generated assertion messages are not as expressive. I'm not sure if that alone is reason enough to implement such a subselector method though and we already declined a roughly similar request in https://github.com/simplabs/qunit-dom/issues/761.

What I could imagine us doing though is to support passing in { element, description } objects. The assertion messages could then use the description to build expressive messages and an unrelated library could find the right DOM nodes based on the search text and build these expressive descriptions. This would potentially also allow something like page objects to make better use of qunit-dom.

Turbo87 avatar Nov 10 '20 21:11 Turbo87