I have the following route rule:
get '/reports/stats_by_date', to: 'reports#stats_by_date'
And rake routes gives me this:
reports_stats_by_date GET /reports/stats_by_date(.:format) reports#stats_by_date
That looks correct. So I'm trying to test my controller from within rake with this function:
def test_reports_should_load
get :reports_stats_by_date, :start_date => '2013-10-01', :end_date => '2013-10-05', :format => :json
assert_response :success
end
Pretty simple. But when I run rake test, I get the following error:
ReportsControllerTest#test_reports_should_load:
ActionController::UrlGenerationError: No route matches {:start_date=>"2013-10-01", :end_date=>"2013-10-05", :format=>:json, :controller=>"reports", :action=>"reports_stats_by_date"}
test/controllers/reports_controller_test.rb:6:in `test_reports_should_load'
For some reason, Rails is trying to load up the action :reports_stats_by_date when the route clearly points to reports#stats_by_date. What did I do wrong here?
I think it's because you only need to reference the action name, not the name of the path. stats_by_date instead of reports_stats_by_date
def test_reports_should_load
get :stats_by_date, :start_date => '2013-10-01', :end_date => '2013-10-05', :format => :json
assert_response :success
end
Related
I have the following route, that appears in the list when I perform "rake routes":
page_upload_image POST /pages/:page_id/upload_image(.:format) pages#upload_image
I also have the following in my routes file:
resources :pages do
post :sort, :on => :collection
post :upload_image, :on => :collection
end
I'm then using JavaScript to capture and POST values pulled from the following:
%form.new-page-image{:class => "hide", :action => "/pages/#{#page.id}/upload_image"}
%input.page_image{:type => "file", :name => "page[image]", :multiple => "true"}
I have the following for my upload_image action in my pages controller:
def upload_image
image = params[:page][:image]
uploader = PageImageUploader.new
uploader.store!(image)
render json: uploader.to_json
end
For some reason, even though the route exists, when I post to it, I get the following:
ActionController::RoutingError (No route matches [POST] "/pages/1/upload_image"):
I'm wondering why a route, that appears legitimate (shows up properly when executing rake routes) would return this error when I try to post to it.
Try changing your routes to this instead, as it looks like you want a member route instead of a collection route:
resources :pages do
post :sort, :on => :collection
post :upload_image, :on => :member
end
I would also advise against using interpolation in the route, as it can quickly get long and messy. Instead try to name your routes using as: and call them using the names instead.
Rspec is not recognising my controller routes. I am using Versionist gem to version my API and I am using a path version (so /v1/ to version my API as shown below.).
constraints :subdomain => "api" do
api_version(:module => "V1", :path => {:value => "v1"}, :defaults => {:format => :json}, :default => true) do
match '/orders' => 'orders#index', :via => :get
The route in rake routes is shown as:
GET /v1/orders(.:format) V1/orders#index {:subdomain=>"api", :format=>:json}
My controller is located in app/controller/v1/orders_controller.rb.
For the rspec test, I have a orders_controller_spec.rb, I have:
require 'spec_helper'
module V1
describe OrdersController do
describe "GET #index" do
it "throws an error on incorrect params" do
get :index
end
end
end
end
The error I get is:
1) V1::OrdersApiController GET #index throws an error on incorrect param
Failure/Error: get :index
ActionController::RoutingError:
No route matches {:controller=>"v1/orders"}
What is wrong here? How come no route matches v1/orders? In rake routes, I see the route right there as shown above: GET /v1/orders(.:format) V1/orders#index {:subdomain=>"api", :format=>:json}. It says GET /v1/orders. Where is the problem here?
This is my route
match "/:type/:brand/:model/:plate" => "site/vehicles#show",
:constraints => {:plate => /[a-z]{3}\d{4}/}, :as => :vehicle
It passes the route tests
# the route test passess
it "routes to #show" do
{:get => '/carro/volksvagen/gol-2-0/abc1234'}.should route_to(
"site/vehicles#show",
:type => "carro",
:brand => "volksvagen",
:model => "gol-2-0",
:plate => "abc1234"
)
end
But after upgrading rails (3.2.0 => 3.2.8 ) which also updated journey (1.0.0 => 1.0.4), the following CONTROLLER test (which IMHO should not check for routes, which it apparently did not, back in rails 3.2.0) started failing.
describe "#show" do
it "should be success" do
get :show, :plate => #vehicle.plate
response.should be_success
end
end
It raises
Site::VehiclesController#show should be success
ActionController::RoutingError:
No route matches {:plate=>"ABC1672", :controller=>"site/vehicles",
:action=>"show"}
And even if I complete all the route vars
describe "#show" do
it "should be success" do
get :show, :plate => #vehicle.plate, :model => 'model',
:type => 'type', :brand => 'brand'
response.should be_success
end
end
I get:
# No route matches {:plate=>"ABC1586", :model=>"model", :type=>"type",
:brand=>"brand", :controller=>"site/vehicles", :action=>"show"}
The application still works, but I will not know when it stops, since my tests are failing.
Anyone solved/had similar issue?
I know 'not upgrading rails' could avoid getting this errors, as suggested in a similar question, but I don't think it is a solution.
Routing error when updating to Rails 3.2.6 or Rspec 2.11.0
Thank you in advance.
Edit:
vehicle /:type/:brand/:model/:plate(.:format) site/vehicles#show {:plate=>/[a-z]{3}\d{4}/}
I think your problem is in a mismatch between your regex and your test data. In your error message, I see:
No route matches {:plate=>"ABC1586", :model=>"model", :type=>"type",
:brand=>"brand", :controller=>"site/vehicles", :action=>"show"}
But the route has the following regex for plate:
:plate => /[a-z]{3}\d{4}/
That requires all lower-case letters; upper case letters won't match. So you need to either fix your test data, or fix the regex in your route.
I have a constrained route that matches usernames like this:
controller :users, :path => '/:username', :as => :user, :constrain => { :username => /^_?[a-z]_?(?:[a-z0-9]_?)*$/i } do
# lots of nested routes go here
end
When I go to write RSpec tests for this (versus using user_id like normal), all the tests are failing because it "can't find the route" even though it works fine on the server.
describe "for an invalid request" do
it "should render a 404 if an associated photo is not found" do
# give it a bad photo id
xhr :post, :destroy, :id => "999999", :photo_id => "999999", :username => #photo_owner.username
# not found
response.status.should == not_found
end
end
This test was working fine when I was using the user_id in my routes prior to switching to usernames:
resources :users do
# nested routes
end
and
xhr :post, :destroy, :id => "999999", :photo_id => "999999", :user_id => #photo_owner.id
So what am I doing wrong and what has changed?
My server console shows this which means I should have all of the parameters passed in properly:
Processing by TagsController#destroy as JS
Parameters: {"constrain"=>{"username"=>/^_?[a-z]_?(?:[a-z0-9]_?)*$/i}, "username"=>"rubynewb", "photo_id"=>"2004-the-title-of-the-photo-here", "id"=>"1797"}
Use :constraints => {...} in your route definition.
You have one too many parameters being passed...
"constrain"=>{"username"=>/^_?[a-z]_?(?:[a-z0-9]_?)*$/i}
Rails doesn't recognize :constrain, therefore it and it's contents are passed along as a parameter instead of being processed by the Rails router.
I have a RESTful resource in my Rails app called "Photo". I'm using Paperclip to serve different "styles" of my photos (for thumbnails and the like), and I'm using a custom route to RESTfully access those styles:
map.connect "photos/:id/style/*style", :controller => "photos", :action => "show"
That's working fine, but I want to write a test to make sure it stays that way.
I already have a functional test to call the Photo controller's show action (generated by scaffold in fact):
test "should show photo" do
get :show, :id => photos(:one).to_param
assert_response :success
end
That tests the execution of the action at the URL "/photo/1". Now I want to test the execution of the URL "/photo/1/style/foo". Unfortunately, I can't seem to get ActionController::TestCase to hit that URL; the get method always wants an action/id and won't accept a URL suffix.
How do I go about testing a custom URL?
Update
While checking on #fernyb's answer I found this snippet in the same rdoc
In tests you can simply pass the URL or named route to get or post.
def send_to_jail
get '/jail'
assert_response :success
assert_template "jail/front"
end
However, when I actually try that, I get an error message:
test "should get photo" do
get "/photos/1/style/original"
assert_equal( "image/jpeg", #response.content_type )
end
ActionController::RoutingError: No route matches {:action=>"/photos/1/style/original", :controller=>"photos"}
I wonder if I'm doing something wrong.
Use assert_routing to test routes:
assert_routing("/photos/10/style", :controller => "photos", :action => "show", :id => "10", :style => [])
assert_routing("/photos/10/style/cool", :controller => "photos", :action => "show", :id => "10", :style => ["cool"])
assert_routing("/photos/10/style/cool/and/awesome", :controller => "photos", :action => "show", :id => "10", :style => ["cool", "and", "awesome"])
In your integration test you can then do:
test "get photos" do
get "/photos/10/style/cool"
assert_response :success
end
From the Rails API documentation:
Route globbing
Specifying *[string] as part of a
rule like:
map.connect '*path' , :controller => 'blog' , :action => 'unrecognized?'
will glob all remaining parts of the
route that were not recognized
earlier. The globbed values are in
params[:path] as an array of path
segments.
So it looks like you need to pass the :path arguments, to test the action correctly.