I'm really stuck here. I have a Language model, that gets updated in this method:
def update
#language = Language.find(params[:id])
if #language.update_attributes(language_params)
flash[:success] = 'Language information updated.'
redirect_to #language
else
#skill_errors = #language.errors
render 'edit'
end
end
The intended behaviour for a successful update reproduces when I run it on my local server, object gets updated, flash appears and redirect to #language happens.
In the test, however, I only get the 200: Success response, and the object doesn't get updated. Here's the test code:
test 'should allow update when logged in as admin user' do
sign_in(#admin)
patch language_path(#ruby_language), params: { language: { name: 'Test'} }
assert_not flash.empty?
assert_redirected_to #ruby_language
#ruby_language.reload
assert_equal 'Test', #ruby_language.name
end
#admin and #ruby_language are defined in fixtures. All the asserts in this test fail, including the last one, with reload. My guess is that there might be some routing glitch caused by my usage of Devise and/or Kaminari gems? On the other hand, my Language routes are very simple:
resources :languages, concerns: :paginatable (the concern is here for human-readable URL formatting). Please, keep in mind that everything works as intended, only tests fail for some reason... Thanks in advance!
It turned out I was simply missing a required parameter in my update hash. Used Arun Kumar's tip of adding puts #response.body after patch.
Related
A User can submit a form to create a Scheduling from more than one place and should subsequently be returned to the original place of form submission.
My Schedulings Controller, therefore relies on request.referrer. It works as intended in development and looks something like this:
class SchedulingsController < ApplicationController
#stuff not relevant to the question removed
def create
#scheduling = current_user.schedulings.build(scheduling_params)
if #scheduling.save
redirect_to request.referrer
flash[:success] = "scheduled!"
else
# do something not relevant to the question
end
end
end
I wish to run a Rails integration test to test this. request.referrer however appears to always be nil in the Test environment, so with help from an answer here I have worked around this by including a headers hash in the Post request like this:
class SchedulingsCreateTest < ActionDispatch::IntegrationTest
test "valid input for new scheduling" do
assert_difference 'Scheduling.count', 1 do
post schedulings_path, params: { scheduling: { start_time: Time.now },
headers: { "HTTP_REFERER" => "http://example.com/workouts" }
end
follow_redirect!
assert_template 'workouts/index'
assert_not flash.empty?
end
This test fails at assert_not flash.empty?
What is happening, why is the flash assessed as empty?
I note that if, in the controller, I change redirect_to request.referrer to redirect_to workouts_path (or workouts_url), the test passes.
Thanks for your interest and any help.
Daniel
I have broadly solved my own question by changing the value in the headers hash from:
"http://example.com/workouts" to "http://www.example.com/workouts"
the former is shown in an answer here and is sourced directly from the Rails Guide, however working in Rails 5, I found the “www” is necessary.
I got to the bottom of this with an extra line in my test:
assert_redirected_to workouts_url before the follow_redirect!, which failed and identified the url discrepancy.
Daniel
This is kind of a weird question so I'll probably be editing this to fill in some context as needed. I have an RSpec test:
it "should update object paramaters" do
put :update, params: {id: test_project, project: valid_params}
test_project.reload
expect(test_project.title).to eql valid_params[:title]
expect(test_project.created_at).to_not eql test_project.updated_at
end
Relevant controller action:
# #project is defined in a before_action
def update
if #project.update_attributes(project_params)
redirect_to #project, flash: { success: "Project successfully updated!" }
else
render :edit
end
end
This request returns a 200 OK (I would expect a redirect code, but this is not the case) response code, however when I reload test_project the title remains unchanged and the test fails. This EXACT same request works to update the Project in the development and production environments. Any clues as to why this isn't working?
I don't actually see a reload in the test (you should do one there). The 200 would suggest either (a) there's a user authentication step that you've not handled in your tests or (b) there's a validation issue. You can test for either / both by using gem 'pry' and binding.pry in your update method. If the pry doesn't execute in update, then update isn't executing (perhaps user authentication issue) and if it does execute, you can look at #project.errors.full_messages to see what the issue is.
Just starting out in using Test::Unit but having a problem nailing down a redirect test:
test "should destroy line_item" do
assert_difference('LineItem.count', -1) do
delete :destroy, id: #line_item
end
assert_redirected_to controller: 'carts', action: 'show'
end
which throws the following error:
Failure: Expected response to be a redirect to <http://test.host/carts/980190962> but was a redirect to <http://test.host/carts/980190963>.
test_should_destroy_line_item(LineItemsControllerTest)
test/functional/line_items_controller_test.rb:47:in `block in <class:LineItemsControllerTest>'
The docs state the following:
assert_redirected_to(options = {}, message=nil) public
Assert that the redirection options passed in match those of the redirect called in the latest action. This match can be partial, such that assert_redirected_to(:controller => "weblog") will also match the redirection of redirect_to(:controller => "weblog", :action => "show") and so on.
but assert_redirected_to controller: 'carts' leads to an even more outright failure:
Failure: Expected response to be a redirect to <http://test.host/carts> but was a redirect to <http://test.host/carts/980190963>.
test_should_destroy_line_item(LineItemsControllerTest)
If the documentation is correct, what am I missing? If it is not, what alternatives do I have to test the redirect regardless of a matching id?
It appears that the documentation for assert_redirected_to is not entirely correct, but part of the problem had to do with the cart_id being different at the setup stage (when #line_item is created) as compared to the stage where it is destroyed. So the workaround is to modify the fixture/controller such that it will have the same cart_id at the time of destruction. It doesn't solve the real problem with assert_redirected_to but at least the test will pass.
I'm trying to switch from using respond_to to respond_with in Rails controllers. Everything's going smoothly, except for testing invalid saves in controller specs. Here's an example:
describe MyController do
...
describe "PUT update" do
context "with invalid attributes" do
it "should re-render the edit page" do
style = stub_model(Style)
Style.stub(:find) { style }
Style.any_instance.stub(:save).and_return(false)
put :update
response.should render_template(:edit)
end
end
end
end
This works just fine with my old respond_to style update action, but with respond_with, I get
Failure/Error: response.should render_template("edit")
So, in short - how do I test this? ...Or should I just assume render_with knows what it's doing and not test at all? Any general suggestions?
Cheers in advance
PS: The update action:
def update
#style = Style.find(params[:id])
flash[:notice] = "Style updated" if #style.update_attributes(params[:style])
respond_with(#style)
end
I've been looking into this exact thing (how I found this topic) - so far I have the following:
Location.any_instance.stub(:valid?).and_return(false)
Location.any_instance.stub(:errors).and_return('anything')
(where Location is my model that uses respond_with)
however I believe there must be a nicer way to do it - if I find it, I'll be sure to post it!
Note: I'm also using the responders gem so one of these lines may not be necessary for you if you're not using it!
I'm getting a failing test here that I'm having trouble understanding. I'm using Test::Unit with Shoulda enhancement. Action in users_controller.rb I'm trying to test...
def create
unless params[:user][:email] =~ / specific regex needed for this app /i
# ...
render :template => 'sessions/new'
end
end
Test...
context 'on CREATE to :user' do
context 'with invalid email' do
setup { post :create, { 'user[email]' => 'abc#abcd' } }
should_respond_with :success
end
# ...
end
Fails because "response to be a <:success>, but was <302>". How is it 302?
Change action to...
def create
render :template => 'sessions/new'
end
Test still fails.
#Ola: You're wrong: POST is connected to create. PUT is normally connected to update.
A :forbidden is quiet odd though. Here are some suggestions to find the problem (I've never used Shoulda, but I don't think it is a problem with Shoulda.
Make sure the route is defined in config/routes.rb and check with rake routes
Do you have any before_filters that could be responsible for that behaviour (login filter, acts_as_authenticated etc..)? Checkout log/test.log. A halt in the filter chain shows up there.
Print out the response body puts response.body to see what you get returned.
Hope this helps.
If you're using default REST-ful URLs, you probably should use PUT, not POST... Since PUT is connected to create, POST to that URL will give you an unauthorized and redirect.