Search code examples
rubyautomationcucumbercapybara

Selecting a CSS element with a dynamic id


I'm writing automated tests using cucumber and SitePrism, and I'm having trouble selecting a CSS element between tests because its id is dynamic (changes with the user id) and the name isn't unique. The element is a user role dropdown menu, hence the id changing to match the user id.

The HTML for the element is...

<dd>
   <select id="select-role-a02322d1-8add-4234-aeca-02d3fca2a239" name="role_id">
      <option title="System Administrator Role" value ="1">Administrator</option>
      <option title="Secure Content Viewer" value="2">SecureContentView</option>
   </select>
</dd>

When I set the element on the page model as...

element :role_dropdown, 'select[name=role_id]'

And execute following object/instance...

And(/^select the first value in the Add Role dropdown$/) do
    @page.user.role_dropdown.select("Administrator")
end

I am returned

Capybara::Ambiguous: Ambiguous match, found 2 elements matching css "select[name=role_id]"
from /Users/Alex/.rvm/gems/ruby-2.1.2@railstutorial_rails_4_0/gems/capybara-2.4.3/lib/capybara/node/finders.rb:38:in 
`block in find'

So to get the test to work, I must set the element to the static id of

element :role_dropdown, '#select-role-8ec3f391-3871-47ff-b605-8f43aa40677d'

But then the element is useless in all instances where the user with that id is not being tested.

  1. Is there any way to set up the element on the page model to have for a dynamic id?

  2. In the instance below (figure 1), how can I go about selecting the value of 1 instead of the option's text? I would like the make what's being selected pertain to the value, not text. This way if the title or text of option 1 changes, option 1 will still be selected and the test won't fail.

Figure 1:

And(/^select the first value in the Add Role dropdown$/) do
    @page.user.role_dropdown.select("Administrator")
end
  1. If the id is dynamic, how do I go about defining {id}? Can I define it using a key placed in environment_keys.yaml?

Solution

  • I'm assuming the id is being generated externally and not accessible to the test (in which case Anthony's suggestion may not work)

    If that is the case, select[name=role_id] may be a good start. Apparently there are two matching elements on the page with this selector, so you're going to need something more specific to differentiate them.

    To find both, open developer tools and go to the console. Assuming the site has jQuery, you can do $('select[name=role_id]') to find the matching elements. You can right click on them to reveal in elements panel. There might be something higher in the tree that you can use to select them.

    There's a possibility that one is visible and one is hidden. If that's the case, then you can select just the visible one like this: element :role_dropdown, 'select[name=role_id]', visible: true