I figured I should finally write some tests for my rails app.
My controller is "UsersController". It doesn't have any HTML as I just have an iphone app sending a post in to a rails controller.
Here is my test:
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def test_create
# to http post
# /users
#user[email]=%#&user[password]=%#&user[password_confirmation]=%#
#post
post(:create, :user => {:password => "testpassword", :password_confirmation => "testpassword"})
end
Problem is that I get this error:
1) Error:
test_create(UsersControllerTest):
ActionView::MissingTemplate: Missing template users/new with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths
So I guess it's trying to populate an HTML page? If so, I find this odd. I would think it would directly do the post to the controller. Can someone confirm that this "post" method tries and populates an HTML form?
If this is the case, how should I proceed in writing a test to directly send an HTTP post to the controller?
Thanks for any help
You can specify "format" to make it work:
post(:action, {'param1'=>'value1', 'param2' => 'value2', :format => 'js'})
Unless you tell it otherwise the post method assumes the requested content type is HTML. Typically the create action looks something like this:
#user = User.new(params[:user])
if #user.save
redirect_to posts_path
else
render :new
end
If the action fails it tries to render 'users/new', which doesn't exist, thus the error.
So there are a couple of issues here. It's not clear what content type is expected (XML?). The action is failing, but we can't see why. It might help to edit the question to show us what the controller action does.
Related
I am trying to conditionally route two different controller actions. I have created RoutesController#root and sent root there from routes.rb, however the app just wants to find a root template to render no matter what i write in the root method.
What I am trying to achieve is:
user requests ‘/’
user gets pushed to sign in
upon successful sign in if current_user.company.present? (current_user should be available in the Routes controller right?) then render Quotes#new
else if no company then render Companies#new
I'm hitting a missing template error;
Missing template companies/1/quotes/new.1 with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder]}. Searched in: * "app/views"
I want it to be searching in app/views/quotes/new, what am i doing wrong?
RoutesController.rb
class RoutesController < ActionController::Base
before_filter :authenticate_user!
def root
if current_user.company.present?
render new_company_quote_path(current_user)# 'quotes#new'
else
render new_company_path(current_user) # 'companies#new'
end
end
end
routes.rb
root 'routes#root'
render is used when you just want to render/display a particular view from the path, it doesn't execute any code. For detailed differences, see this post.
Thus, in your case, it should be redirect_to instead of render.
And regarding the best practice thing, it looks good to me.
In my Rails app, I have in the Application controller
respond_to :json
A controller that inherits Application controller responds with json like so in the action...
# Some code
if mission_updated.eql? true
render :json => {}
else
render :json => {}
end
However, whenever I run a rspec test in reference to the above action
it "should return appropriate response" do
post :update_unlocked_missions
parsed_body = JSON.parse(response.body)
parsed_body.should == {}
end
I'm returned with the following rspec error
ActionView::MissingTemplate:
Missing template api/v1/missions/update_unlocked_missions, api/v1/base/update_unlocked_missions with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder, :coffee, :rabl, :haml]}. Searched in:
* "#<RSpec::Rails::ViewRendering::EmptyTemplatePathSetDecorator:0x007f9ea2903b00>"
My question is why is it going to the view when it should respond with json and how do I fix this?
Try testing with an action that's just render json: {}. If that works, the problem is probably something in mission_updated.
I get this when I try and run my view:
Missing template application/login with {:formats=>[:html], :locale=>[:en], :handlers=>[:coffee, :erb, :builder]}. Searched in: * "/home/carladessi/Goods In Final/app/views"
in my controller I have:
def login
# respond_to do |format|
# format.html
end
and in my routes I have:
match "/login/", :controller => 'application', :action => 'login'
I'm guessing I need to put something else in the controller I just don't know what.. sorry if this is a really blatant question!
Restarted the server and it works fine !
It is not really conventional Rails to render views from the application_controller.
However, what is happening is Rails is looking for an actual template or view to be here:
RAILS_ROOT/app/views/application/login.html.erb
What you can do is add/create that template at the above path. Or you can redirect to another controller (which exists and does render an actual template).
Currently working on a project, and have encountered a problem that I have never come across before. Currently doing a login sign up page that ask the user to sign up. I had a undefined method `name'error before, and then realised that the method is not called name it was called full_name. I have gone through all the folders to ensure that any method or attribute is not called 'name' and renamed it to 'full_name. Having refreshed the browser I recieve the following error which I haven't seen before. Can some please explain what this error is and how possibly I may go about resolving it.
Template is missing
Missing template users/create with
{:handlers=>[:erb, :rjs, :builder,
:rhtml, :rxml], :formats=>[:html],
:locale=>[:en, :en]} in view paths
"C:/Users/patterd/Documents/Project/app/views"
This error happens if you don't redirect in the create method of your controller.
Are you redirecting in the create method in the controller or rendering the new form, in case of error?
Without the redirection in the create method in the controller, you need to make a new file called create.html.erb. Usually, after successful creation, you redirect to some other page like shown below
def create
# some object you want to create
# if the object.save is fine
# redirect_to object
# else
# render new with the errors
# end
end
In my case I had to process and render no view.
def return_payment
# do lots of stuff
head :ok
end
I had the same problem and the reason was that I left accidentally other empty 'create' method :)
Generally missing template error occurs
-when you don't have view file of that method of controller, or
-if a method is just for calculation that does not have any view file, then you must have to render/redirect the method.
If you do not render or redirect the method, it will search for the view page of current method name (in your case it will search for create.html.erb).So, you have to render/redirect the method.
I had the same problem and just added the redirect_to and it worked!
def update
#visitor = Visitor.find(params[:id])
if #visitor.update_attributes(visitor_params)
flash[:notice] = "Update ok!"
redirect_to root_path #just added this line and it worked!
else
render 'edit'
end
end
I am trying to implement some integration tests for my application to test a voting system I have in place but have run into some problems. First off, here is the test code I am trying to get to pass:
describe "vote_up_user" do
it "should update the user rating" do
click_link "user_up_arrow"
response.should have_selector("#user_rating", :content => "1")
end
end
Here is the link that gets clicked:
<%= link_to image_tag("uparrowbig.png"), vote_up_user_path(#user), :method => :post,
:id => "user_up_arrow", :class => "arrow", :remote => true %>
The corresponding action:
respond_to :html, :js
def vote_up_user
#voted_on_user = User.find(params[:id])
current_user.vote_exclusively_for(#voted_on_user)
respond_with(#voted_on_user, :location => user_path(#voted_on_user))
end
and in case anyone is interested the corresponding votes/vote_up_user.js.erb:
$("user_rating").update('<%= #voted_on_user.plusminus.to_s %>')
$("user_up_arrow").update('<%= image_tag("uparrowbigselect.png") %>')
$("user_down_arrow").update('<%= image_tag("downarrowbig.png") %>')
My problem is that I keep failing at the click_link line with the following error:
Missing template votes/vote_up_user with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]}
I can understand why this is failing as I do not have a template that is html.erb in the specified path. I actually have a js.erb file instead as this is an AJAX call, but this is not included in the :formats array and thus is not found. My question is then, what would be the best way to ensure that the :js format is search for when the integration test clicks on the link? Is this something I can simply adjust in the test or will I need to add it to the link helper?
I suspect the reason it's not working is that RSpec alone can't test Javascript.
When you add remote => true to a link, it only adds data-remote="true" as an attribute of the link, which doesn't mean anything without Javascript. That's why you see in your error :formats=>[:html]. It is only going to look for html views. In order for Rails to request the .js.erb view by default, you either need to have the .js on the end of the URL that it is requesting or actually use Javascript to request the page.
To get Javascript to actually run in your tests, you need to use something like Capybara. When you run your test, you'll actually see your browser start up and it will run your test actually in the browser.
If this is what you want to do, I would recommend watching Ryan Bates' recent Railscast: http://railscasts.com/episodes/257-request-specs-and-capybara
Update based on comments
respond_with will only redirect to the location you specify on POST, PUT, or DELETE requests. While you have :method => :post in the link, links will always generate GET requests when Javascript is disabled (since you're not using AJAX). Without Javascript, the only way to generate a POST request is with a form tag.
If you want it to degrade gracefully in this situation, you should either create an html view for these situations or put a block after the respond_with like this:
respond_with(#voted_on_user, :location => user_path(#voted_on_user)) do |format|
format.html { redirect_to user_path(#voted_on_user) }
end`