这里的大多数答案都从底层改变了内容,并且与用户交互不同。这是一个接近用户所做的版本。
# waits for the text to show up in autocomplete and then selects it
def selectize_select(selectize_class, text)
find("#{selectize_class} .selectize-input input").native.send_keys(text) #fill the input text
find(:xpath, "//div[@data-selectable and contains(., '#{text}')]").click #wait for the input and then click on it
# convert css selector to xpath selector using Nokogiri::CSS.xpath_for
end
我创建了一个助手,并将其混合到我的水豚功能规格中:
module PageSteps
def fill_in_selectized(key, *values)
values.flatten.each do |value|
page.execute_script(%{
$('.#{key} .selectize-input input').val('#{value}');
$('##{key}').selectize()[0].selectize.createItem();
})
end
end
end
这是一个如何使用它的示例:
# Single value
fill_in_selectized('candidate_offices', 'Santa Monica')
# Multiple values
fill_in_selectized('candidate_offices', ['San Francisco', 'Santa Monica'])
第一个参数是一个“键”,根据我们的标记,它可以在我们的应用程序中工作。根据您的标记,您可能需要进行一些调整。这需要启用 Javascript 的水豚驱动程序(我们使用poltergeist)。
API 允许,但需要先添加选项,然后才能设置值:
var selectize = $('.selector')[0].selectize
selectize.addOptions([{text: 'Hello', value: 'Hello'}, {text: 'World', value: 'World'}])
selectize.setValue(['Hello', 'World'])
这是我与我的功能规格混合在一起的帮手。它调整并扩展了Christian 的答案。
select
和 text
输入类型fill_in
方法find_field
的标识符来查找输入。因此,您可以使用标签的文本、元素的 id 或元素的名称来查找元素。此代码所做的唯一假设是您的文本输入具有
name
属性(当然,Rails 输入帮助程序会自动添加)
def selectize(key, with:)
field = page.find_field(key, visible: false)
case field.tag_name
when "select"
page.execute_script(%{
$("select[name='#{field["name"]}']")
.selectize()[0].selectize.setValue(#{Array(with)});
})
else
Array(with).each do |value|
page.execute_script(%{
$("input[name='#{field["name"]}']")
.next()
.find(".selectize-input input").val('#{value}')
.end()
.prev()
.selectize()[0].selectize.createItem();
})
end
end
end
使用示例:
selectize "Single-choice field", with: "Only option"
selectize "Multi-choice field", with: ["Option A", "Option B"]
在 2022 年,上述方法对我来说都不起作用,这是我现在使用的:
def selectize_select(option_name, from:)
page.execute_script <<~JS
const id = $('label:contains(#{from.to_json})').attr('for').replace(/-selectized$/, '')
const selectize = $(`#${id}`).selectize({})[0].selectize;
selectize.setValue(selectize.search(#{option_name.to_json}).items[0].id);
JS
end
它匹配标签和选项名称,而不是输入 ID 和选项值:
selectize_select 'Capybara', from: 'Your favorite animal'
selectize
使用所有按键事件(keydown
、keypress
、keyup
)来提供出色的 UI,但似乎没有提供从 javascript 设置数据的简单方法。
syn.js
库来触发右键事件。这是一个有效的助手:
def fill_in_selectize_area selector, options
# Syn appears to require an id, so assign a temporary one
@selectize_unique_id ||= 0
unique_id = "temp_selectize_id_#{@selectize_unique_id +=1}"
with = options.fetch(:with)
page.execute_script %Q{
var selectize = $(#{selector.to_json})[0].selectize;
var type = #{with.to_json}.join(selectize.settings.delimiter) + '\t';
selectize.$control_input.attr('id', #{unique_id.to_json});
Syn.click({}, #{unique_id.to_json}).delay().type(type);
}
# make sure that it worked *and* that it's finished:
page.should have_content with.join('×') << '×'
end
# example use:
fill_in_selectize_area '[name="blog[tags]"]', with: ['awesome subject', 'other tag']
请注意,需要
delay
,因为专注于输入并不是即时的。
我有多种方法来填写选择输入,但没有一种方法适用于根据用户输入动态加载选项的情况。这是需要的,因为否则 select 会有几千个选项,并且页面加载速度会非常慢。
这是最终起作用的版本(它基于此线程中投票最多的答案,但具有改进的 CSS 选择器)
def fill_in_selectize(key, options = {})
# fill the input text
find("##{key} + .selectize-control .selectize-input input").native.send_keys(options[:with])
# wait for the input and then click on it
find(:xpath, "//div[@data-selectable and contains(., '#{options[:with]}')]").click
end