Anyone know how to get RSpec to call a singular route when testing controller?
It can't find the route b/c it doesn't know to look for a singular controller so I need a way to specify it.
routes.rb
resource :settings_group, :path => "/settings/scheduling/"
settings_groups_controller_spec.rb
describe SettingsGroupsController do
describe "GET show" do
let(:describe_action) { get :show }
it "sets #settings_group" do
describe_action
assigns(:settings_group).should be_kind_of(SettingsGroup)
end
end
end
...
ActionController::RoutingError:
No route matches {:controller=>"settings_groups"}
Just out of curiosity, but why does settings_group_controller.rb have
describe SettingsGroupsController (with an s)
Shouldn't they match?
Related
I'm getting unexpected errors when running some Rspec tests. They are
1) PeopleController redirects when loading root should redirect to the splash page
Failure/Error: get '/'
ActionController::UrlGenerationError:
No route matches {:action=>"/", :controller=>"people"}
...
2) PeopleController redirects when loading /people/show should redirect to the base person path
Failure/Error: get '/show' #/show
ActionController::UrlGenerationError:
No route matches {:action=>"/show", :controller=>"people"}
I don't understand why Rspec can't find the routes.
From the controller, people_controller.rb:
class PeopleController < ApplicationController
...
def show
redirect_to people_path
end
def index
#people = Person.all
end
...
From the Rspec file people_controller_spec.rb:
describe PeopleController do
describe "redirects" do
context "when loading root" do
it "should redirect to the temp page" do
get '/'
last_response.should be_redirect
follow_redirect!
last_request.url.should include('/temp')
end
end
context "when loading /people/show" do
it "should redirect to the base people path" do
get '/people/show'
last_response.should be_redirect
follow_redirect!
last_request.url.should include('/people')
end
end
end
end
And my routes:
$ rake routes
Prefix Verb URI Pattern Controller#Action
...
person GET /people/:id(.:format) people#show
...
root GET / redirect(301, /temp)
routes.rb:
Rails.application.routes.draw do
resources :temp
resources :people
# map '/' to be a redirect to '/temp'
root :to => redirect('/temp')
end
What am I missing to get the routes from test to match up? I could see the root test not working because it's not technically handled by the People controller (I tried putting it in as a sanity test and only made myself more confused) but the /show failure really makes no sense to me.
Inside a controller test the method get takes an action argument, not a path. If the resource is a member (as opposed to a collection), you must also specify the id parameter, so:
get :show, id: 1
will call the #show action on an instance of PeopleController, with a params hash including {id: '1'}.
This is described in more detail in the Guide to Testing Rails Applications.
I'm trying to write a controller test and Rspec isn't finding routes that I know exist and work fine on a development server.
In my routes I have a catch-all route that should redeirect to a generic controller if someone goes to a route that isn't predefined.
routes.rb
namespace :tools do
match '*unmatchedpath' => "generic#show", :via => :get
end
generic_controller.rb
def show
# do stuff
end
generic_controller_spec.rb
require 'spec_helper'
describe Tools::GenericController do
describe 'GET show' do
it 'does stuff' do
get :show
end
end
Here is the error I get from rspec when I run the test above
1) Tools::GenericController GET show does stuff
Failure/Error: get :show
ActionController::RoutingError:
No route matches {:controller=>"tools/generic", :action=>"show"}
All routes work as expected on my development server so I'm not sure why Rspec isn't finding the route.
Try:
get '*unmatchedpath' => 'tools/generic#show'
I have defined a custom route in
routes.rb
get "packages/city/:location_id", to: "packages#index"
In controller_spec.rb,
get :index
gives this error,
ActionController::UrlGenerationError:
No route matches {:action=>"index", :controller=>"packages"}
How to explicitly specify the custom routes in controller specs?
Perhaps it helps if you declare your route like this?
get "packages/city/:location_id" => "packages#index"
Remember to provide a location_id param in specs, e.g. get :index, location_id: 1.
2017
I tried the solutions above but they did not work. I got:
ArgumentError:
unknown keyword: location_id
It seems that RSpec now requires a params parameter. The corresponding call would look like this:
get(:index, params: { location_id: 123 })
it's because you are not passing location_id
the route is defined to match:
/packages/city/:location_id
so in order to comply with it you need to do something like
get :index, location_id: 1234
Had the same issue with Controller spec:
# rake routes | grep media_order
teacher_work_media_orders PATCH /teacher/works/:work_id/media_orders(.:format) teacher/media_orders#update
when I did:
# spec/controller/teacher/media_orders_controller
patch :update data: {}
I got
Failure/Error: patch :update
ActionController::UrlGenerationError:
No route matches {:action=>"update", :controller=>"teacher/media_orders"}
but when I did
patch :update, work_id: 1234, data: {}
that worked
2019
Was tackling this same error on my controller specs. Tried accepted and follow up solutions, but they also did not work, either led to no method error or persisted the no route match error.
Directly defining the route like in the accepted solution also did not satisfy the errors.
After much searching and some keyboard smashing tests pass.
Things to note
controller is for polymorphic resource
routes are nested within the resources :location, only[:index, :show] do ... end
this is API routes, so JSON only
Solution
let(:location) do
create(:location)
end
shared_examples("a user who can't manage locations") do
describe 'GET #index' do
it 'denies access' do
get :index, params:{location_id: location.locationable.id, format: :json}
expect(response).to have_http_status :unauthorized
end
end
end
So in the end it was a combination of both solutions, but had to put them in the params hash or else it would throw name/no method or route errors
Conclusion
references to the association must be in the params hash
even if controller responds_to :json, it will throw errors no route errors
must include a data hash in your request or no route match errors will appear
Hope this helps,
Cheers!
I have tests like those:
RSpec.describe RestaursController, :type => :controller do
context "GET /restaurs/:id" do
before do
#rest = FactoryGirl.create :restaur
end
context "resource exists" do
subject { get "restaurs/#{#rest.id}"}
it { expect(subject).to render_template(:show) }
end
context "resource doesn't exists" do
subject { get "restaurs/#{#rest.id + 1}" }
it { expect(subject).to redirect_to(:root) }
end
end
end
When I run those tests RSpec says:
Failure/Error: subject { get "restaurs/#{#rest.id}"}
ActionController::UrlGenerationError:
No route matches {:action=>"restaurs/7", :controller=>"restaurs"}
But I think my routes are OK. Look on rake routes log
Prefix Verb URI Pattern Controller#Action
restaurs GET /restaurs(.:format) restaurs#index
POST /restaurs(.:format) restaurs#create
new_restaur GET /restaurs/new(.:format) restaurs#new
edit_restaur GET /restaurs/:id/edit(.:format) restaurs#edit
restaur GET /restaurs/:id(.:format) restaurs#show
PATCH /restaurs/:id(.:format) restaurs#update
PUT /restaurs/:id(.:format) restaurs#update
DELETE /restaurs/:id(.:format) restaurs#destroy
root GET / restaurs#index
Have you got any ideas? What is the problem? Maybe it is about RSpec syntax or something like that?
That isn't how you get actions in a controller test. The argument to get is the name of the action, not a routable path. Routing isn't involved in testing controllers, and neither is rake routes.
You're giving it the action name "restaurs/7", which obviously isn't the real name of a method on your controller. Instead, you should be using get :show to invoke the actual method "show" on your controller, and then passing a hash of parameters:
get :show, id: #rest.id + 1
Similarly, you would use get :index, not get "/", and you would use get :edit, id: ..., not get "/restaurs/#{...}/edit". It's the actual method your meant to test on your controller, not whether a route actually leads you to the correct method.
As a related aside, your opening context is out of place. You shouldn't be using GET /restaurs:/:id as a context. Routing isn't involved here. Just test the method names.
I;m trying to write a spec that tests a controller that is namespaced, let's call it Admin::FooController. My spec is called admin_foo_controller_spec.rb. In the spec, I'm trying to write a very basic spec to see if it can retrieve an action of a controller.
describe "GET 'index'" do
it "should be successful" do
get 'index'
response.should be_success
end
end
But instead I get an error:
Failure/Error: get 'index'
No route matches {:controller=>"admin/foo"}
For another action, I have basically the same test, and I get that the response is not successful. In the actual webapp, I can access these urls fine. One thing I should mention is that this isn't a RESTful resource (it makes no sense as one) so it's really just a group of related administrative actions, so in my routes.rb it's basically like
namespace :admin do
scope "foo" do
match "action1" => "foo#action1"
match "action2" => "foo#action2"
match "/index" => "foo#settings"
match "settings" => "foo#settings"
end
end
Any ideas what I'm doing wrong? It seems like namespacing is asking for trouble with rails, especially for a novice like me. Thanks!
In your route your have no index action in you Foo controller try to get 'settings'
describe "GET 'index'" do
it "should be successful" do
get 'settings'
response.should be_success
end
end
In a controller spec you need define the action of your controller not the real route. You try the routes in a integration test.