diff --git a/lib/capybara/node/matchers.rb b/lib/capybara/node/matchers.rb index 09e87f03..2a3eb4c7 100644 --- a/lib/capybara/node/matchers.rb +++ b/lib/capybara/node/matchers.rb @@ -345,13 +345,18 @@ module Capybara # # page.has_select?('Language', :selected => ['English', 'German']) # - # It's also possible to check if a given set of options exists for + # It's also possible to check if the exact set of options exists for # this select box: # - # page.has_select?('Language', :options => ['English', 'German']) + # page.has_select?('Language', :options => ['English', 'German', 'Spanish']) + # + # You can also check for a partial set of options: + # + # page.has_select?('Language', :with_options => ['English', 'German']) # # @param [String] locator The label, name or id of a select box # @option options [Array] :options Options which should be contained in this select box + # @option options [Array] :with_options Partial set of options which should be contained in this select box # @option options [String, Array] :selected Options which should be selected # @return [Boolean] Whether it exists # diff --git a/lib/capybara/selector.rb b/lib/capybara/selector.rb index 3b101ebc..a5d85c17 100644 --- a/lib/capybara/selector.rb +++ b/lib/capybara/selector.rb @@ -127,7 +127,11 @@ end Capybara.add_selector(:select) do xpath { |locator| XPath::HTML.select(locator) } failure_message { |node, selector| "no select box with id, name, or label '#{selector.locator}' found" } - filter(:options) { |node, options| options.all? { |option| node.first(:option, option) } } + filter(:options) do |node, options| + actual = node.all(:xpath, './/option').map { |option| option.text } + options.sort == actual.sort + end + filter(:with_options) { |node, options| options.all? { |option| node.first(:option, option) } } filter(:selected) do |node, selected| actual = node.all(:xpath, './/option').select { |option| option.selected? }.map { |option| option.text } ([selected].flatten - actual).empty? diff --git a/lib/capybara/spec/session/has_select_spec.rb b/lib/capybara/spec/session/has_select_spec.rb index 4d53597e..df5da522 100644 --- a/lib/capybara/spec/session/has_select_spec.rb +++ b/lib/capybara/spec/session/has_select_spec.rb @@ -1,4 +1,4 @@ -shared_examples_for "has_select" do +shared_examples_for "has_select" do describe '#has_select?' do before { @session.visit('/form') } @@ -14,14 +14,14 @@ shared_examples_for "has_select" do context 'with selected value' do it "should be true if a field with the given value is on the page" do - @session.should have_select('form_locale', :selected => 'English') - @session.should have_select('Region', :selected => 'Norway') + @session.should have_select('form_locale', :selected => 'English') + @session.should have_select('Region', :selected => 'Norway') @session.should have_select('Underwear', :selected => ['Briefs', 'Commando']) end it "should be false if the given field is not on the page" do - @session.should_not have_select('Locale', :selected => 'Swedish') - @session.should_not have_select('Does not exist', :selected => 'John') + @session.should_not have_select('Locale', :selected => 'Swedish') + @session.should_not have_select('Does not exist', :selected => 'John') @session.should_not have_select('City', :selected => 'Not there') @session.should_not have_select('Underwear', :selected => ['Briefs', 'Nonexistant']) @session.should_not have_select('Underwear', :selected => ['Briefs', 'Boxers']) @@ -48,16 +48,31 @@ shared_examples_for "has_select" do end end - context 'with options' do + context 'with exact options' do it "should be true if a field with the given options is on the page" do - @session.should have_select('form_locale', :options => ['English']) - @session.should have_select('Region', :options => ['Norway', 'Sweden']) + @session.should have_select('Region', :options => ['Norway', 'Sweden', 'Finland']) + @session.should have_select('Tendency', :options => []) end it "should be false if the given field is not on the page" do - @session.should_not have_select('Locale', :options => ['Not there']) - @session.should_not have_select('Does not exist', :options => ['John']) + @session.should_not have_select('Locale', :options => ['Swedish']) + @session.should_not have_select('Does not exist', :options => ['John']) @session.should_not have_select('City', :options => ['London', 'Made up city']) + @session.should_not have_select('Region', :options => ['Norway', 'Sweden']) + @session.should_not have_select('Region', :options => ['Norway', 'Norway', 'Norway']) + end + end + + context 'with partial options' do + it "should be true if a field with the given partial options is on the page" do + @session.should have_select('Region', :with_options => ['Norway', 'Sweden']) + @session.should have_select('City', :with_options => ['London']) + end + + it "should be false if a field with the given partial options is not on the page" do + @session.should_not have_select('Locale', :with_options => ['Uruguayan']) + @session.should_not have_select('Does not exist', :with_options => ['John']) + @session.should_not have_select('Region', :with_options => ['Norway', 'Sweden', 'Finland', 'Latvia']) end end end @@ -77,14 +92,14 @@ shared_examples_for "has_select" do context 'with selected value' do it "should be false if a field with the given value is on the page" do - @session.should_not have_no_select('form_locale', :selected => 'English') - @session.should_not have_no_select('Region', :selected => 'Norway') + @session.should_not have_no_select('form_locale', :selected => 'English') + @session.should_not have_no_select('Region', :selected => 'Norway') @session.should_not have_no_select('Underwear', :selected => ['Briefs', 'Commando']) end it "should be true if the given field is not on the page" do - @session.should have_no_select('Locale', :selected => 'Swedish') - @session.should have_no_select('Does not exist', :selected => 'John') + @session.should have_no_select('Locale', :selected => 'Swedish') + @session.should have_no_select('Does not exist', :selected => 'John') @session.should have_no_select('City', :selected => 'Not there') @session.should have_no_select('Underwear', :selected => ['Briefs', 'Nonexistant']) @session.should have_no_select('Underwear', :selected => ['Briefs', 'Boxers']) @@ -111,19 +126,31 @@ shared_examples_for "has_select" do end end - context 'with options' do + context 'with exact options' do it "should be false if a field with the given options is on the page" do - @session.should_not have_no_select('form_locale', :options => ['English']) - @session.should_not have_no_select('Region', :options => ['Norway', 'Sweden']) + @session.should_not have_no_select('Region', :options => ['Norway', 'Sweden', 'Finland']) end it "should be true if the given field is not on the page" do - @session.should have_no_select('Locale', :options => ['Not there']) - @session.should have_no_select('Does not exist', :options => ['John']) + @session.should have_no_select('Locale', :options => ['Swedish']) + @session.should have_no_select('Does not exist', :options => ['John']) @session.should have_no_select('City', :options => ['London', 'Made up city']) + @session.should have_no_select('Region', :options => ['Norway', 'Sweden']) + @session.should have_no_select('Region', :options => ['Norway', 'Norway', 'Norway']) + end + end + + context 'with partial options' do + it "should be false if a field with the given partial options is on the page" do + @session.should_not have_no_select('Region', :with_options => ['Norway', 'Sweden']) + @session.should_not have_no_select('City', :with_options => ['London']) + end + + it "should be true if a field with the given partial options is not on the page" do + @session.should have_no_select('Locale', :with_options => ['Uruguayan']) + @session.should have_no_select('Does not exist', :with_options => ['John']) + @session.should have_no_select('Region', :with_options => ['Norway', 'Sweden', 'Finland', 'Latvia']) end end end end - -