In Capybara, how can I refer to a select knowing only part of its name?
I have the following piece of HTML
<select name="user[work_hours][HASH][end_hour]">
...
</select>
Where HASH is an unknown value, and I need to find the select.
Can I use a regular expression?
There are many ways to do what you want. Depending on surrounding HTML you may be able to scope the find to a section of the page that only includes the one select so you don't need to specify anything to match the select at all
find('css to locate wrapping/scoping element').find(:select)
If that's not possible you can use CSS attribute begins-with and ends-with selectors like
find('select[name^="user[work_hours]["][name$="][end_hour]"]')
If that seems too complicated you can use the :element selector type which will allow you to match on any attribute with a string or regex. This may be inefficient on large pages with many select elements.
find(:element, :select, name: /user\[work_hours\]\[.*\]\[end_hour\]/
Another solution if the options in the select are unique on the page would just be to select the option and not worry about finding the actual select element
select('text of option')
Related
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 dataattributes 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 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
I have two select tags/controls and I need the second select tag options to be dynamically generate based on the selection of first
For example I want to make after selecting a car brand in first select, the second must show the models of selected car brand, But I have not been able to do it please help
Please watch rails cast #88 dynamic select menus revised. The method you need to do this called grouped_collection_select
This method along with the proper coffee script (or JavaScript if you prefer that more than coffeescript) discussed in the video will complete exactly what you're looking for
I am trying to get a hook on a select and set the selected option. I am struggling to do this because my drop down is generated in a loop so the id changes.
Normally I would do something like this
select product_template.name, :from => "product_product_template_id
What if the ID can change
e.g. product_product_presentations_attributes_0_presentation_id
Is there a way to leverage the select function and specify a css selector?
Thanks.
select also accepts label (as in the actual <label> text for that select) and name attributes for the :from option, so if those are not generated / changed all the time, you can use them for a less brittle test.
If that doesn't cut it, you can add a unique CSS class to your select and then select a specific option with something like:
find("select.new_css_class").find("option[value='THE OPTION VALUE YOU WANT']").select_option
So, I'm trying to select a polymer custom element(using paper_elements) in my view with querySelector. I'm able to select regular html elements just fine. In particular, I'm trying to select a specific paper-input element. I want to be able to query it's input element which is buried in it's second shadowroot.
I've tried the following:
querySelector('#my-paper-input::shadow #input')
querySelector('paper-input::shadow input')
and a bunch of other variations. However, no matter what I do, the query always returns null. It's driving me mad because I can style it in css. What do?
As far as I know you have to use several steps
querySelector('#my-paper-input').shadowRoot.querySelector('input');
but you should also be able to access the value using the attribute of the outer element like
querySelector('#my-paper-input').attributes['value'] or
querySelector('#my-paper-input').attributes['inputValue']
you could also use http://pub.dartlang.org/packages/angular_node_bind
but I wasn't able using Angular with paper-elements recently (see https://github.com/angular/angular.dart/issues/1227)
I need to render a <select> with some values.
Those values correspond to a model that the rendered view's model belongs_to - e.g. Foo has_many Bar, I'm rendering Bar, and its form should include Foo's ids and names in the <select>.
That is no problem - right now I'm using simple_form for that.
But in addition to a fixed set of values, the user should be able to insert a new Foo aynchronously (in some popup / whatever), updating the <select> in the browser with the newly-generated id, and the given name.
That is no problem to implement by hand, but is there a Rails feature (like UJS) or plugin (like simple_form) which provides exactly that?
You can try selectize-rails
Examples can be found here. http://brianreavis.github.io/selectize.js/