I have been using Jason Garber’s form_test_helper plugin. Basically, if you’ve ever had it where you rename a parameter in a form - change your test accordingly (post :action, :id => 1, :name => ‘George’ becoming post :action, :id => 1, :first_name => ‘George’) and forget to update your view, form_test_helper is for you. Instead you ask your controller to render your form and then call submit_form, supplying it the parameters you want. It parses your form, looks for the fields and then submits it to the Url embedded in the form tag. So the above would fail unless you actually had a field named first_name in your UI. Anyway, I thoroughly recommend it for avoiding embarrassing bugs.
However, it does not work with xhr requests. So, in Jason’s absence (he’s away at the moment), I’ll show you the changes needed here. It’s nowhere near complete but it does the trick for me.
Grab the plugin and edit vendor/plugins/form_test_helper/lib/form_test_helper.rb.
Around line 444-ish:
# Alias for select_form when called with a block. # Shortcut for select_form(name).submit(args) without block. def submit_form(*args, &block) @ix_xhr = false internal_submit_form(*args, &block) end
# As submit_form but sends an XHR request def submit_form_xhr(*args, &block) @ix_xhr = true internal_submit_form(*args, &block) end
def internal_submit_form(*args, &block) if block_given? select_form(*args, &block) else selector = args[0].is_a?(Hash) ? nil : args.shift select_form(selector).submit(*args) end end
And around line 480-ish:
def make_request(method, path, params={}, referring_uri=nil) if self.kind_of?(ActionController::IntegrationTest) self.send(method, path, params.stringify_keys, {:referer => referring_uri}) else params.merge!(ActionController::Routing::Routes.recognize_path(path, :method => method)) if params[:controller] && params[:controller] != current_controller = self.instance_eval("@controller").controller_name raise "Can't follow links outside of current controller (from #{current_controller} to #{params[:controller]})" end self.instance_eval("@request").env["HTTP_REFERER"] ||= referring_uri # facilitate testing of redirect_to :back if @is_xhr self.xhr(method, params.delete(:action), params.stringify_keys) else self.send(method, params.delete(:action), params.stringify_keys) end end end
As I say, it’s a bit of an ugly hack but it works for me. I will submit it to Jason once I have tidied it up.
Eagerly looking forward to your contribution!
Jason