-
-
Save jcieslar/6491810f4fd9fada0ab3 to your computer and use it in GitHub Desktop.
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 |
My 1 ct contribution:
def selectize_single_select(field, value)
page.execute_script %Q{ $('.#{field} .selectize-input').click(); }
page.execute_script %Q{ $('.#{field} .selectize-dropdown-content .option:contains("#{value}")').click(); }
end
def selectize_multi_select(field, *values)
values.flatten.each do |tag|
page.execute_script "$('.#{field} .selectize-input').click();"
page.execute_script %Q{ $('.#{field} .selectize-dropdown-content').children("div:contains('#{tag}')").click(); }
page.execute_script "$('body').mousedown()"
end
end
I came up with this slight mod on @christiannelson's solution. I was unable to use his as written because it is counting on the DOM structure as generated by SimpleForm. My app is using formtastic which does not put a class on the wrapper (instead it uses an id).
I've modified the helpers to make them a bit more generic so they work for both these form builders (and probably others). Instead of depending on the class/id of the field's wrapper class, they count on the fact that selectize
builds it's DOM as a sibling of the base form field.
module SelectizeSelectHelper
def find_selectized_control_js(key)
%{ $('##{key}.selectized').next('.selectize-control') }.strip
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.
page.execute_script %{ #{find_selectized_control_js(key)}.find('.selectize-input').click(); }
page.execute_script %{ #{find_selectized_control_js(key)}.find(".selectize-dropdown-content .option:contains(\\\"#{value}\\\")").click(); }
end
# Select one or more items from a selectized select input where multiple=true.
def selectize_multi_select(key, *values)
values.flatten.each do |value|
page.execute_script(%{
#{find_selectized_control_js(key)}.find('input').val("#{value}");
$('##{key}.selectized')[0].selectize.createItem();
})
end
end
end
Note: you'll see the quoting around value
. I was having trouble where the "value" send it occasionally had an apostrophe (like O'Reilly
). You may adjust the handling of value
for your particular data.
To deselect an item simply use
def deselect_single_select(key, value)
page.execute_script %Q{ #{find_selectized_control_js(key)}.find('.selectize-input .item:contains("#{value}") .remove').click(); }
end
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
})
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
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
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
This is where I landed... separate helpers for
multiple=false
andmultiple=true
selects: