Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use capybara to select a select2 drop-down field

There is help online for using select2 with capybara (see links below), but no help in particular as far as I have seen for select2 drop-down fields. I have tried all kinds of things, including trying to fill in the field when :js => false (using something along the lines of find(:xpath, "//input[@id='product_manufacturer_id']").set "Test product manufacturer") or variations on the solutions that work on other select2 fields (see links given below). Nothing is working for me so far.

Notes on my configuration:

  • Using select2 version 3
  • Using capybara WebKit
  • This particular field is also using simple form, and is an association (so has f.association...). Particularly, ProductManufacturer instances are in a has_many relationship with products.
  • The select2 drop-down field is supposed to be dynamically populated by ProductManufacturer instances which match the query text (i.e., the text you type into the search field).

In case it is helpful to see how I am implementing the factory:

Here is my factory file:

factory :product do
  name "Test product"
  url { Faker::Name.name.parameterize }
  access_level 1
  product_manufacturer
end

factory :product_manufacturer do
  name "Test product manufacturer"

  factory :product_manufacturer_with_product do
    transient do
      products_count 1
    end

    after(:create) do |product, evaluator|
      create_list(:product,
                   evaluator.products_count,
                   product: product)
    end
  end
end

And then, before the test starts, I run:

@product_manufacturer = create(:product_manufacturer)

My latest attempt: My helper method (which is working for my other select2 fields):

def select2_choose(id, options)
  page.execute_script  "$('#{id}').trigger('keydown').val('{options[:query]}').trigger('keyup');"
  find(".select2-result-label", :text => options[:choose]).click
end

And then how I implement it:

select2_choose( "#s2id_autogen7", 
  :query => @product_manufacturer.name[0...-2], 
  :choose => @product_manufacturer.name)

Which outputs the following error message:

Failure/Error: create_product
Capybara::ElementNotFound:
   Unable to find css ".select2-result-label" with text "Test product manufacturer"

(which basically means that it has found and clicked on the drop-down box, and it has put in the query text, "Test product manufacture". But select2 was not finding the option from the database to find it.)

Note that I have successfully used factory_girl to generate my ProductManufacturer instance object @product_manufacturer, and calling things such as puts @product_manufacturer is successful, returning the instance object: ProductManufacturer:0x007f0145f9cb38>.

Here is a screenshot from right before the test fails: screenshot

Other questions that are related but do not fully solve this issue:

- Selecting select2 drop downs (but not in capybara):

How to select option in drop down using Capybara

Unable to select item in Select2 drop down

- Selecting select2 options in capybara (but not with drop downs):

How to test a Select2 element with capybara DSL? (Note: I successfully used answers from here to select non-drop-down select2 fields)

- selecting select2 drop-down using selenium

Selenium Select2 command for drop-down box

like image 304
RyanQuey Avatar asked Dec 21 '16 07:12

RyanQuey


People also ask

How do you select options in capybara?

Method: Capybara::Node::Actions#select If from option is present, #select finds a select box, or text input with associated datalist, on the page and selects a particular option from it. Otherwise it finds an option inside current scope and selects it.

How do I make Select2 disabled?

Disabling a Select2 control Select2 will respond to the disabled attribute on <select> elements. You can also initialize Select2 with disabled: true to get the same effect.


1 Answers

Capybara's field actions (fill_in, set, etc) only work with basic html form fields, not with JS driven widgets since they usually hide the basic fields. The key to working with any JS driven widget in Capybara is to perform the actions a user would have to perform, which in this case is click on the visible element to trigger the dropdown then click on the element you want to select.

As an example, to select "California" from the first select2 dropdown on the example page http://select2.github.io/examples.html it could be done like

first('.select2-container', minimum: 1).click
find('li.select2-results__option[role="treeitem"]', text: 'California').click

If you want to do it by typing in the search term instead of clicking on the result it would be something like

first('.select2-container', minimum: 1).click
find('.select2-dropdown input.select2-search__field').send_keys("California", :enter)

Using execute_script and trigger are bad ideas if you're testing a web app since it bypasses most of the checks on what a user could actually do, they're fine if you're just automating a page

like image 132
Thomas Walpole Avatar answered Nov 01 '22 14:11

Thomas Walpole