Skip to content

Commit

Permalink
work on adding react select
Browse files Browse the repository at this point in the history
  • Loading branch information
twalpole committed Sep 24, 2018
1 parent 9047631 commit e4ca801
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
1 change: 1 addition & 0 deletions capybara.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Gem::Specification.new do |s|
s.add_development_dependency('launchy', ['>= 2.0.4'])
s.add_development_dependency('minitest')
s.add_development_dependency('puma')
s.add_development_dependency('byebug')
s.add_development_dependency('rake')
s.add_development_dependency('rspec', ['>= 3.4.0'])
s.add_development_dependency('selenium-webdriver', ['~>3.5'])
Expand Down
49 changes: 49 additions & 0 deletions lib/capybara/plugins/react_select.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

module Capybara
module Plugins
class ReactSelect
def select(scope, value, **options)
select = find_react_select(scope, value, options).click
option = scope.find(:react_select_option, value)
option.click
end

def unselect(scope, value, **options)
select = find_react_select(scope, value, options)
raise Capybara::UnselectNotAllowed, 'Cannot unselect option from single select box.' unless select2.has_css?('.select2-selection--multiple')
select.click
option = scope.find(:react_select_option, value)
option.click
end

private

def find_react_select(scope, value, from: nil, **options)
if from
scope.find(:react_select, 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('react-select')][XPath.attr(:class).contains_word('react-select-container')])
end
end
end
end
end

Capybara.add_selector(:react_select) do
xpath do |locator, **options|
XPath.css('.select__control')[XPath.following_sibling(:input)[XPath.attr(:name) == locator]]
end
end

Capybara.add_selector(:react_select_option) do
xpath do |locator|
xpath = XPath.anywhere(:div)[XPath.attr(:class).contains_word('select__menu')]
xpath = xpath.descendant(:div)[XPath.attr(:class).contains_word('select__option')]
xpath = xpath[XPath.string.n.is(locator.to_s)] unless locator.nil?
xpath
end
end

Capybara.register_plugin(:react_select, Capybara::Plugins::ReactSelect.new)
61 changes: 61 additions & 0 deletions lib/capybara/spec/session/plugin_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require 'capybara/plugins/select2'
require 'capybara/plugins/react_select'

Capybara::SpecHelper.spec 'Plugin', requires: [:js] do
before do
Expand Down Expand Up @@ -83,4 +84,64 @@
@session.select 'Miss', from: 'Title', using: nil
expect(@session.find_field('Title').value).to eq('Miss')
end

context "with react select 2", :focus_ do
before do
@session.visit('https://react-select.com/home')
end

it 'should select an option' do
@session.select 'Florida', from: 'Click this to focus the single select element', using: :react_select
expect(@session).to have_field(type: 'select', with: 'FL', visible: false)
end

it 'should remain selected if called twice on a single select' do
@session.select 'Florida', from: 'Click this to focus the single select element', using: :react_select
@session.select 'Florida', from: 'Click this to focus the single select element', using: :react_select
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: :react_select
@session.select 'California', from: 'Click this to focus the multiple select element', using: :react_select
expect(@session).to have_select(multiple: true, selected: %w[Pennsylvania California], visible: false)
@session.unselect 'Pennsylvania', from: 'Click this to focus the multiple select element', using: :react_select
expect(@session).to have_select(multiple: true, selected: %w[California], visible: false)
@session.unselect 'California', from: 'Click this to focus the multiple select element', using: :react_select
expect(@session).to have_select(multiple: true, selected: %w[], visible: false)
end

it 'should not reselect if already selected' do
@session.select 'Pennsylvania', from: 'Click this to focus the multiple select element', using: :react_select
@session.select 'Pennsylvania', from: 'Click this to focus the multiple select element', using: :react_select
expect(@session).to have_select(multiple: true, selected: %w[Pennsylvania], visible: false)
@session.unselect 'Pennsylvania', from: 'Click this to focus the multiple select element', using: :react_select
@session.unselect 'Pennsylvania', from: 'Click this to focus the multiple select element', using: :react_select
expect(@session).to have_select(multiple: true, selected: %w[], visible: false)
end

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

it 'should work with name', :focus_ do
@session.select 'Purple', from: 'color', using: :react_select
expect(@session).to have_css('input[type=hidden][name=color]', visible: false) { |el| el.value == 'purple' }
end

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

it 'works when called on the select box' do
el = @session.find(:css, 'select#id_label_single', visible: false)
el.select 'Florida', using: :react_select
expect(@session).to have_field(type: 'select', with: 'FL', visible: false)
end

end
end

0 comments on commit e4ca801

Please sign in to comment.