Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capybara writing drop down's options texts into an array

Tags:

ruby

capybara

I'd like to put a dropdown list's options into an array generically in capybara. After the process I'm expecting to have an arrray of strings, containing all dropdown options. I've tried the code below but the length of my array stays 1 regardless of what the option count is.

periods = Array.new()
periods = all('#MainContent_dd')
print periods.length
like image 755
Alper Mermer Avatar asked Feb 21 '13 15:02

Alper Mermer


2 Answers

The problem is that all('#MainContent_dd') returns all elements that have the id MainContent_dd. Assuming this is your dropdown and ids are unique, it is expected that the periods.length is 1 (ie periods is the select list).

What you want to do is get the option elements instead of the select element.

Assuming your html is:

<select id="MainContent_dd">
    <option>Option A</option>
    <option>Option B</option>
    <option>Option C</option>
</select>

Then you can do:

  periods = find('#MainContent_dd').all('option').collect(&:text)
  p periods.length
  #=> 3
  p periods
  #=> ["Option A", "Option B", "Option C"]

What this does is:

  1. find('#MainContent_dd') - Finds the select list that you want to get the options from
  2. all('option') - Gets all option elements within the select list
  3. collect(&:text) - Collects the text of each option and returns it as an array
like image 136
Justin Ko Avatar answered Nov 15 '22 00:11

Justin Ko


@JustinCo's answer has a problem if used driver isn't fast: Capybara will make a query to driver for every invocation of text. So if select contains 200 elements, Capybara will make 201 query to browser instead of 1 which may be slow.

I suggest you to do it using one query with Javascript:

periods = page.execute_script("options = document.querySelectorAll('#MainContent_dd > option'); texts=[]; for (i=0; i<options.length; i++) texts.push(options[i].textContent); return texts")

or (shorter variant with jQuery):

periods = page.evaluate_script("$('#MainContent_dd').map(function() { return $(this).text() }).get()")
like image 42
Andrei Botalov Avatar answered Nov 14 '22 22:11

Andrei Botalov