From 368708760a94d769e316ad044816f87964929727 Mon Sep 17 00:00:00 2001 From: Thomas Walpole Date: Sun, 9 Sep 2018 16:51:13 -0700 Subject: [PATCH] implement unselect in select2 plugin --- lib/capybara.rb | 1 + lib/capybara/plugins/select2.rb | 22 ++++++++++++++++++---- lib/capybara/spec/session/plugin_spec.rb | 20 +++++++++++++++++++- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/lib/capybara.rb b/lib/capybara.rb index 9b55d29e67..f29af53caf 100644 --- a/lib/capybara.rb +++ b/lib/capybara.rb @@ -521,6 +521,7 @@ module Selenium; end config.test_id = nil config.predicates_wait = true config.default_normalize_ws = false + config.default_plugin = { select: nil, unselect: nil, check: nil, uncheck: nil, choose: nil } end Capybara.register_driver :rack_test do |app| diff --git a/lib/capybara/plugins/select2.rb b/lib/capybara/plugins/select2.rb index 7e8e1e923a..d8e9fce403 100644 --- a/lib/capybara/plugins/select2.rb +++ b/lib/capybara/plugins/select2.rb @@ -3,15 +3,29 @@ module Capybara module Plugins class Select2 - def select(scope, value, from: nil, **options) - select2 = if from + def select(scope, value, **options) + select2 = find_select2(scope, value, options).click + option = scope.find(:select2_option, value) + option[:"aria-selected"] != 'true' ? option.click : select2.click + end + + def unselect(scope, value, **options) + select2 = find_select2(scope, value, options) + raise Capybara::UnselectNotAllowed, 'Cannot unselect option from single select box.' unless select2.has_css?('.select2-selection--multiple') + select2.click + option = scope.find(:select2_option, value) + option[:"aria-selected"] == 'true' ? option.click : select2.click + end + + private + + def find_select2(scope, value, from: nil, **options) + 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 diff --git a/lib/capybara/spec/session/plugin_spec.rb b/lib/capybara/spec/session/plugin_spec.rb index 1e30fdca61..d4eb5774fd 100644 --- a/lib/capybara/spec/session/plugin_spec.rb +++ b/lib/capybara/spec/session/plugin_spec.rb @@ -28,11 +28,29 @@ 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: :select2 + @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) + @session.unselect 'Pennsylvania', from: 'Click this to focus the multiple select element', using: :select2 + 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: :select2 + 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: :select2 + @session.select 'Pennsylvania', from: 'Click this to focus the multiple select element', using: :select2 + 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: :select2 + @session.unselect 'Pennsylvania', from: 'Click this to focus the multiple select element', using: :select2 + expect(@session).to have_select(multiple: true, selected: %w[], visible: false) end it 'should work with id' do