Skip to content

Instantly share code, notes, and snippets.

@jcieslar
Created March 19, 2015 16:33
Show Gist options
  • Save jcieslar/6491810f4fd9fada0ab3 to your computer and use it in GitHub Desktop.
Save jcieslar/6491810f4fd9fada0ab3 to your computer and use it in GitHub Desktop.
Capybara and selectize
page.execute_script("$('.selectize-input input').val('ber')")
sleep 0.5
page.execute_script("$('.selectize-input input').keyup()")
sleep 0.5
page.execute_script("$('.full-name').mousedown()")
# https://github.com/brianreavis/selectize.js/blob/master/src/selectize.js
@jonathanhoskin
Copy link

jonathanhoskin commented May 27, 2018

On large lists of options, the .click() method described above doesn't work, as selectize doesn't populate the fake options collection with all the options for performance reasons.

A potential hack around is to just initialize the selectize with a huge maxOptions:

$(el).selectize({
  maxOptions: 3000
})

@jjinkxy
Copy link

jjinkxy commented Mar 15, 2019

Leaving this here for any one who not only wants to add multiple but also create a new item. This worked for me.

# Example (model: teacher, attribute: student_list):
# fill_in_selectize_multi "teacher_student_list", with: %w(Jo Maren Bobby)

def fill_in_selectize_multi(field, options = {})
  selector = "'##{field}-selectized'"

  values = options[:with]
  values.each do |tag|
    page.execute_script "$(#{selector}).closest('.selectize-control').find(' .selectize-input').click();"
    page.execute_script("$(#{selector}).val('#{tag}')")
    page.execute_script("$(#{selector}).keyup().focus()")
    page.execute_script %{ $(#{selector}).closest('.selectize-control').find(' .selectize-dropdown-content').children("div:contains('#{tag}')").click(); }
    page.execute_script "$('body').mousedown()"
  end

@aleko-812
Copy link

Another version of the same.

  def selectize_single_select(selector, value)
    page.execute_script(%{
      var $select = $('#{ selector }').selectize();
      var selectize = $select[0].selectize;
      selectize.setValue(#{ value });
    })
  end
  def selectize_multi_select(selector, *values)
    page.execute_script(%{
      var $select = $('#{ selector }').selectize();
      var selectize = $select[0].selectize;
      selectize.setValue(#{ values });
    })
  end

To DRY this code a bit one could implement it as one method with extra-parameter. Like:

def fill_in_selectize(selector, multi=false, *values)
  ...
end

@bunnymatic
Copy link

Here's yet another version of the same. I recently did some shuffling of code such that jQuery was not in the global namespace. Instead it's imported as needed. So my test helpers no longer had access to jQuery. This moves the helper code to using vanilla with querySelector{All} instead of the jquery finder helpers.

module SelectizeSelectHelper
  delegate :execute_script, to: :page

  def find_selectized_control_js(key)
    %{ document.querySelector('##{key}.selectized').nextElementSibling }
  end

  def open_selectize_chooser(key)
    execute_script %{ document.querySelector('##{key}').selectize.open(); }
  end

  def close_selectize_chooser(key)
    execute_script %{ document.querySelector('##{key}').selectize.close(); }
  end

  # Select a single item from a selectized select input where multiple=false given the id for base field
  def selectize_single_select(key, value)
    # It may be tempting to combine these into one execute_script, but don't; it will cause failures.
    open_selectize_chooser(key)
    execute_script %{
                   var options = #{find_selectized_control_js(key)}.querySelectorAll('.option');
                   var option = Array.from(options).find((opt) => opt.innerHTML.match(/#{value}/));
                   option.click() }
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment