Skip to content

Commit

Permalink
Play with idea of plugins to support actions with common UI libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
twalpole committed Mar 12, 2018
1 parent 5143eaa commit 9193bc1
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 2 deletions.
8 changes: 8 additions & 0 deletions lib/capybara.rb
Expand Up @@ -130,6 +130,10 @@ def register_server(name, &block)
servers[name.to_sym] = block
end

def register_plugin(name, plugin)
plugins[name.to_sym] = plugin
end

##
#
# Add a new selector to Capybara. Selectors can be used by various methods in Capybara
Expand Down Expand Up @@ -188,6 +192,10 @@ def servers
@servers ||= {}
end

def plugins
@plugins ||= {}
end

# Wraps the given string, which should contain an HTML document or fragment
# in a {Capybara::Node::Simple} which exposes all {Capybara::Node::Matchers},
# {Capybara::Node::Finders} and {Capybara::Node::DocumentMatchers}. This allows you to query
Expand Down
9 changes: 7 additions & 2 deletions lib/capybara/node/actions.rb
Expand Up @@ -174,8 +174,13 @@ def uncheck(locator = nil, **options)
#
# @return [Capybara::Node::Element] The option element selected
def select(value = nil, from: nil, **options)
scope = from ? find(:select, from, options) : self
scope.find(:option, value, options).select_option
plugin = options.delete(:using)
if plugin
Capybara.plugins[plugin].select(self, value, from: from, **options)
else
scope = from ? find(:select, from, options) : self
scope.find(:option, value, options).select_option
end
end

##
Expand Down
36 changes: 36 additions & 0 deletions lib/capybara/plugins/select2.rb
@@ -0,0 +1,36 @@
module Capybara
module Plugins
class Select2
def select(scope, value, from: nil, **options)
select2 = if from
scope.find(:select2, from, options.merge(visible: false))
else
select = scope.find(:option, value, options).ancestor(:css, 'select', visible: false)
select.find(:xpath, XPath.next_sibling(:span)[XPath.attr(:class).contains_word('select2')][XPath.attr(:class).contains_word('select2-container')])
end
select2.click
scope.find(:select2_option, value).click
end
end
end
end

Capybara.add_selector(:select2) do
xpath do |locator, **options|
xpath = XPath.descendant(:select)
xpath = locate_field(xpath, locator, options)
xpath = xpath.next_sibling(:span)[XPath.attr(:class).contains_word('select2')][XPath.attr(:class).contains_word('select2-container')]
xpath
end
end

Capybara.add_selector(:select2_option) do
xpath do |locator|
xpath = XPath.anywhere(:ul)[XPath.attr(:class).contains_word('select2-results__options')][XPath.attr(:id)]
xpath = xpath.descendant(:li)[XPath.attr(:role) == 'treeitem']
xpath = xpath[XPath.string.n.is(locator.to_s)] unless locator.nil?
xpath
end
end

Capybara.register_plugin(:select2, Capybara::Plugins::Select2.new)
32 changes: 32 additions & 0 deletions lib/capybara/spec/session/select2_plugin_spec.rb
@@ -0,0 +1,32 @@
require 'capybara/plugins/select2'

Capybara::SpecHelper.spec "select2", :focus_, requires: [:js] do
before do
@session.visit('https://select2.org/appearance')
end

it "should select an option" do
@session.select 'Florida', from: 'Click this to focus the single select element', using: :select2

expect(@session).to have_field(type: 'select', with: 'FL', visible: false)
end

it "should work with multiple select" do
@session.select 'Pennsylvania', from: 'Click this to focus the multiple select element', using: :select2
@session.select 'California', from: 'Click this to focus the multiple select element', using: :select2

expect(@session).to have_select(multiple: true, selected: %w[Pennsylvania California], visible: false)
end

it "should work with id" do
@session.select 'Florida', from: 'id_label_single', using: :select2
expect(@session).to have_field(type: 'select', with: 'FL', visible: false)
end

it "works without :from" do
@session.within(:css, 'div.s2-example:nth-of-type(2) p:first-child') do
@session.select 'Florida', using: :select2
expect(@session).to have_field(type: 'select', with: 'FL', visible: false)
end
end
end

0 comments on commit 9193bc1

Please sign in to comment.