I'm improving my tests with RSpec
and capybara-webkit
, trying to delete all the css
and xpath
selectors like
find('#edit_user > div:nth-child(7) > div > div > button').click
and I'm looking for the best option to replace them.
I was going to use the css class
of the elements but some "pro" capybara tester said this is not the best option.
So my question is: can I use the data
attributes in my tests?
If I have an element
<button name="button" type="submit" class="button last" data-test="edit.update">Update/button>
will I be able to do
find('edit.update').click
?
And do you think it is a good idea? If you have more ideas/infos about this topic, feel free to comment!
To check if an HTML element has a specific attribute, you can use the hasAttribute() method. This method returns true if the specified attribute exists, otherwise it returns false . The hasAttribute() method also works for the HTML5 data-* attributes.
To retrieve a data-* attribute value as an unconverted string, use the attr() method. Since jQuery 1.6, dashes in data-* attribute names have been processed in alignment with the HTML dataset API. $( "div" ).
Consider, we have html elements with data attributes. Now, we need to select the above elements by data attribute in JavaScript. To select the single element, we need to use document.querySelector () method by passing a [data-attribute = 'value'] as an argument.
Data attributes are a way to associate data with elements in the DOM. Any attribute that starts with a data- prefix is considered a data attribute. In this post, we will learn how to query for elements using their data attributes.
Using data- as a prefix, you can add a data attribute to store some information within an element (any element). Now, how do you extract and use the data that are associated with the elements? Here, I’ll show you how using a simple jQuery method, you can find elements by its data attribute value. What is data attribute and how to use it?
HTML5 data attributes allow developers to add data to an element. Using data- as a prefix, you can add a data attribute to store some information within an element (any element). Now, how do you extract and use the data that are associated with the elements?
To locate elements by their data-* attribute, you need to use a CSS-selector or XPath.
For the CSS-selector:
find('button[data-test="edit.update"]').click
For XPath:
find('//button[@data-test="edit.update"]').click
Whether or not it is a good idea really depends on the application. You want to pick something that uniquely identifies the element. If "edit.update" is not going to be unique, it would not be a good choice to use. The class
attribute would be fine if the button had a unique class, which "button" and "last" are not likely to be.
The best approach is really to use static id
attributes as they should be unique within the page and are less likely to change. The find
method also supports locating elements by id, which means you do not have to write CSS-selectors or XPath.
The answer given by Justin Ko is correct, I just wanted to add something slightly more advanced which can help with test readability in some situations. You can add your own "selectors" to Capybara, so if you really wanted to select things by a data-test attribute (not a great idea since you don't really want to be adding attributes just for testing) a lot you could do
Capybara.add_selector(:dt) do
css { |v| "*[data-test=#{v}]" }
end
which would allow
find(:dt, 'edit.update')
this can make tests understandable while also limiting complicated css or path queries to a single place in your test code. You can then define a method such as
def find_by_dt(value)
find(:dt, value)
end
if you prefer the look of find_by_dt...) to find(:dt, ...)
You can also add filters and descriptions to your own selections for more flexibility, better error descriptions, etc - see https://github.com/jnicklas/capybara/blob/master/lib/capybara/selector.rb for the built-in selectors provided by capybara
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With