diff --git a/History.txt b/History.txt index 92d5509..2738008 100644 --- a/History.txt +++ b/History.txt @@ -1,6 +1,8 @@ == SVN -* Fix bad reference to #select method in README (Patch from Luke Melia) +* Add save_and_open_page to aid in debugging +* Add radio button support via #chooses method +* Docfix: bad reference to #select method in README (Patch from Luke Melia) * Allow specifying the input name/label when doing a select (Patch from David Chelimsky) * Raise a specific exception if the developer tries to manipulate form elements before loading a page (Patch from James Deville) * Add basic support for Rails-generated JavaScript link tags diff --git a/TODO.txt b/TODO.txt index 4600c74..c3a1813 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,4 +1,3 @@ -Option button support Full support for multiple forms on a page Track the current form based on the location of the last manipulated input, use this as a default for clicks_button Make current_url work with redirections diff --git a/lib/webrat/session.rb b/lib/webrat/session.rb index a709362..28fe945 100644 --- a/lib/webrat/session.rb +++ b/lib/webrat/session.rb @@ -139,6 +139,18 @@ module ActionController add_form_data(input, input.attributes["value"]) end end + + # Verifies that an input radio button exists on the current page and marks it + # as checked, so that the value will be submitted with the form. + # + # Example: + # chooses 'First Option' + def chooses(field) + radio = find_field_by_name_or_label(field) + return flunk("Could not find radio button #{field.inspect}") if radio.nil? + return flunk("Input #{radio.inspect} is not a radio button") unless radio.attributes['type'] == 'radio' + add_form_data(radio, radio.attributes["value"] || "on") + end # Verifies that a submit button exists for the form, then submits the form, follows # any redirects, and verifies the final page was successful. @@ -158,6 +170,21 @@ module ActionController def submits_form(form_id = nil) # :nodoc: end + + # Saves the currently loaded page out to RAILS_ROOT/tmp/ and opens it in the default + # web browser if on OS X. Useful for debugging. + # + # Example: + # save_and_open_page + def save_and_open_page + return unless File.exist?(RAILS_ROOT + "/tmp") + + filename = "webrat-#{Time.now.to_i}.html" + File.open(RAILS_ROOT + "/tmp/#{filename}", "w") do |f| + f.write response.body + end + `open tmp/#{filename}` + end protected # Methods you could call, but probably shouldn't @@ -222,7 +249,7 @@ module ActionController def find_button(value = nil) # :nodoc: return nil unless value - submit_buttons.detect { |el| el.attributes["value"] == value } + submit_buttons.detect { |el| el.attributes["value"] =~ /^\W*#{value}\b/i } end def add_form_data(input_element, value) # :nodoc: @@ -269,7 +296,12 @@ module ActionController debug_log "REQUESTING PAGE: #{method.to_s.upcase} #{url} with #{data.inspect}" @current_url = url self.send "#{method}_via_redirect", @current_url, data || {} - assert_response :success + + if response.body =~ /Exception caught/ || response.body.blank? + save_and_open_page + end + + assert_response :success reset_dom end @@ -343,7 +375,8 @@ module ActionController def add_default_params_for(form) # :nodoc: add_default_params_from_inputs_for(form) add_default_params_from_checkboxes_for(form) - add_default_params_from_textateas_for(form) + add_default_params_from_radio_buttons_for(form) + add_default_params_from_textareas_for(form) end def add_default_params_from_inputs_for(form) # :nodoc: @@ -362,7 +395,16 @@ module ActionController end end - def add_default_params_from_textateas_for(form) # :nodoc: + def add_default_params_from_radio_buttons_for(form) # :nodoc: + (form / "input").each do |input| + next if input.attributes["type"] != "radio" + if input.attributes["checked"] == "checked" + add_form_data(input, input.attributes["value"]) + end + end + end + + def add_default_params_from_textareas_for(form) # :nodoc: (form / "textarea").each do |input| add_form_data(input, input.inner_html) end diff --git a/test/chooses_test.rb b/test/chooses_test.rb new file mode 100644 index 0000000..4357939 --- /dev/null +++ b/test/chooses_test.rb @@ -0,0 +1,74 @@ +require File.dirname(__FILE__) + "/helper" + +class ChoosesTest < Test::Unit::TestCase + + def setup + @session = ActionController::Integration::Session.new + @session.stubs(:assert_response) + @session.stubs(:get_via_redirect) + @session.stubs(:response).returns(@response=mock) + end + + def test_should_fail_if_no_radio_buttons_found + @response.stubs(:body).returns(<<-EOS) +
+
+ EOS + @session.expects(:flunk) + @session.chooses "first option" + end + + def test_should_fail_if_input_is_not_a_radio_button + @response.stubs(:body).returns(<<-EOS) +
+ +
+ EOS + @session.expects(:flunk) + @session.chooses "first_option" + end + + def test_should_check_rails_style_radio_buttons + @response.stubs(:body).returns(<<-EOS) +
+ + + + + +
+ EOS + @session.expects(:get_via_redirect).with("/login", "user" => {"gender" => "M"}) + @session.chooses "Male" + @session.clicks_button + end + + def test_should_only_submit_last_chosen_value + @response.stubs(:body).returns(<<-EOS) +
+ + + + + +
+ EOS + @session.expects(:get_via_redirect).with("/login", "user" => {"gender" => "M"}) + @session.chooses "Female" + @session.chooses "Male" + @session.clicks_button + end + + def test_should_result_in_the_value_on_being_posted_if_not_specified + @response.stubs(:body).returns(<<-EOS) +
+ + +
+ EOS + @session.expects(:post_via_redirect).with("/login", "first_option" => "on") + @session.chooses "first_option" + @session.clicks_button + end + +end \ No newline at end of file diff --git a/test/clicks_button_test.rb b/test/clicks_button_test.rb index d4ba7e3..b765907 100644 --- a/test/clicks_button_test.rb +++ b/test/clicks_button_test.rb @@ -5,7 +5,8 @@ class ClicksButtonTest < Test::Unit::TestCase @session = ActionController::Integration::Session.new @session.stubs(:assert_response) @session.stubs(:get_via_redirect) - @session.stubs(:response).returns(@response=mock) + @response = mock + @session.stubs(:response).returns(@response) end def test_should_fail_if_no_buttons @@ -158,6 +159,20 @@ class ClicksButtonTest < Test::Unit::TestCase @session.clicks_button end + def test_should_send_default_radio_options + @response.stubs(:body).returns(<<-EOS) +
+ + + + + +
+ EOS + @session.expects(:get_via_redirect).with("/login", "user" => {"gender" => "F"}) + @session.clicks_button + end + def test_should_send_correct_data_for_rails_style_unchecked_fields @response.stubs(:body).returns(<<-EOS)
diff --git a/test/visits_test.rb b/test/visits_test.rb index a1146cc..0b89631 100644 --- a/test/visits_test.rb +++ b/test/visits_test.rb @@ -1,10 +1,16 @@ require File.dirname(__FILE__) + "/helper" +RAILS_ROOT = "." unless defined?(RAILS_ROOT) + class VisitsTest < Test::Unit::TestCase + def setup @session = ActionController::Integration::Session.new @session.stubs(:assert_response) @session.stubs(:get_via_redirect) + @response = mock + @session.stubs(:response).returns(@response) + @response.stubs(:body).returns("") end def test_should_use_get