I have the following routes.rb file (part):
resource :user do
resources :orders do
post :verify, :on => :collection
end
end
My controller spec looks like follows:
require 'spec_helper'
describe OrdersController do
describe "#verify" do
it "verifies a recipe" do
post :verify
end
end
end
The spec fails with an ActionController::RoutingError No route matches {:controller=>"orders", :action=>"verify"} even though the route exists and correctly responds in a browser.
Based on your routes, the describe should look like:
describe Users::OrdersController do
...
Ah, my bad! I've completely forgot that I have the rails-translate-routes gem in place and I don't set a default locale!
Related
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 my brands controller in app/controllers/merchant/brands_controller.rb
I'm trying to write a functional test for it. I've defined test class as
require 'test_helper'
class Merchant::BrandsControllerTest < ActionController::TestCase
include Devise::TestHelpers
setup do
#user = users(:one)
sign_in #user
#brand= brands(:one)
end
test "should get index" do
get :index
assert_response :success
end
end
but the tests throw an error saying
ActionController::RoutingError: No route matches {:controller=>"merchant/brands", :action=>"new"}
Why is it using 'merchant/brands' as controller name?
Or can I specify custom route to make a request to 'new' method?
My routes look like this
namespace :merchant do
resources :accounts do
resources :brands
end
end
I
It seems you forgot the accounts part of your route.
Try with
class Merchant::Accounts::BrandsControllerTest
Here's how my routes look like:
/article/:id/:action {:root=>"article", :controller=>"article/article", :title=>"Article"}
Here's how my controller looks like:
# app/controllers/article/article_controller.rb
class ArticleController < ApplicationController
def save_tags
# code here
end
end
I want to test the save_tags action so I write my spec like this:
describe ArticleController do
context 'saving tags' do
post :save_tags, tag_id => 123, article_id => 1234
# tests here
end
end
But when I run this spec, I get the error
ActionController::RoutingError ...
No route matches {:controller=>"article/article", :action=>"save_tags"}
I think the issue is the save_tags action is a general controller action, ie. there's no /article/:id/save_tags in routes. What's the best way to test this controller action?
You're spot on. The issue is that you're looking for a route which doesn't have :id in it, but you don't have one. You'll need to pass a parameter to the post :save_tags of :id, and given the above question, I believe it is what you are calling article_id.
Therefore, try changing your test to:
describe ArticleController do
context 'saving tags' do
post :save_tags, tag_id => 123, id => 1234
# tests here
end
end
Update
Rails might be getting confused because you're using :action in your route and I believe action is either a reserved word or a word that Rails treats as special. Maybe try changing your routes to:
/article/:id/:method_name {:root=>"article", :controller=>"article/article", :title=>"Article"}
And your test to:
describe ArticleController do
context 'saving tags' do
post :save_tags, { :tag_id => 123, :article_id => 1234, :method_name => "save_tags" }
# tests here
end
end
You need a route to map to your controller actions
post '/article/:id/save_tags'
should work, or consider using resources helper to build your routes
# creates the routes new, create, edit, update, show, destroy, index
resources :articles
# you can exclude any you do not want
resources :articles, except: [:destroy]
# add additional routes that require an article in the member block
resources :articles do
member do
post 'save_tags'
end
end
# add additional routes that do NOT require an article in the collection block
resources :articles do
collection do
post 'publish_all'
end
end
I'm trying to test a controller that is inside an engine my application is using. The spec is not within the engine, but in the application itself (I tried to test within the engine but also had problems).
My engine has the following routes.rb:
Revision::Engine.routes.draw do
resources :steps, only: [] do
collection { get :first }
end
end
The engine is mounted on the application routes.rb normally:
mount Revision::Engine => "revision"
When I run rake routes, at the last lines I get:
Routes for Revision::Engine:
first_steps GET /steps/first(.:format) revision/steps#first
root / revision/steps#first
On my engine's controller (lib/revision/app/controllers/revision/steps_controller.rb), I have:
module Revision
class StepsController < ApplicationController
def first
end
end
end
On Rspec, I test this controller with:
require 'spec_helper'
describe Revision::StepsController do
it "should work" do
get :first
response.should be_success
end
end
Then when I run this spec, I get:
ActionController::RoutingError:
No route matches {:controller=>"revision/steps", :action=>"first"}
To be sure that the route doesn't really exist, I added this to the spec:
before do
puts #routes.set.to_a.map(&:defaults)
end
And the result is this:
[...]
{:action=>"show", :controller=>"devise/unlocks"}
{:action=>"revision"}
It has only the :action parameter.
What may be wrong?
When you're trying to test an engine's controllers, you need to specify what route set you want the controller test to use, otherwise it will run it against the main app's. To do that, pass use_route: :engine_name to the get method.
require 'spec_helper'
describe Revision::StepsController do
it "should work" do
get :first, use_route: :revision # <- this is how you do it
response.should be_success
end
end
I'm building a Rails engine under Rails 3.0.12, but I'm having issues with routes when trying to write specs for my engine's controller.
The context
I've been following an Enginex layout. The engine is named Featuring and is not isolated. It does not declare routes by itself: there is no featuring/config/routes.rb file. Instead, a routes_for_feature method is provided for the main application to define engine-specific routes.
##
# featuring/lib/featuring/rails.rb
#
require 'featuring/rails/routing'
module Featuring
class Engine < ::Rails::Engine
end
end
##
# featuring/lib/featuring/rails/routing.rb
#
module ActionDispatch::Routing
class Mapper
def routes_for_feature(feature_name)
resource_name = feature_name.to_s.pluralize.to_sym
resources resource_name, :controller => "featuring/features", :only => [:index, :show], :feature => feature_name.to_s
end
end
end
Following the Enginex template, I have a Dummy app which define the routes as so:
# featuring/spec/dummy/config/routes.rb
Dummy::Application.routes.draw do
routes_for_feature :feature_model
end
The issue
Everything is working fine when I run the rails server for the Dummy app. I can browse to http://localhost:3000/feature_models and the request is successful.
I would like to spec my Featuring::FeaturesController, but I can't get it to find the routes.
Here is the spec:
# featuring/spec/controllers/features_controller_spec.rb
require 'spec_helper'
describe Featuring::FeaturesController do
context "feature_models" do
it "GET index should be successful" do
puts Rails.application.routes.routes
get :index, { :use_route => "featuring", :feature => "feature_models" }
response.should be_success
end
end
end
And here is the result of running this spec:
rspec spec/controllers/features_controller_spec.rb:7
Featuring::FeaturesController
feature_models
GET /feature_models(.:format) {:action=>"index", :controller=>"featuring/features"}
GET /feature_models/:id(.:format) {:action=>"show", :controller=>"featuring/features"}
GET index should be successful (FAILED - 1)
Failures:
1) Featuring::FeaturesController feature_models GET index should be successful
Failure/Error: get :index, { :use_route => "featuring", :feature => "feature_models" }
ActionController::RoutingError:
No route matches {:feature=>"feature_models", :controller=>"featuring/features"}
# ./spec/controllers/features_controller_spec.rb:8:in `block (3 levels) in <top (required)>'
As you can see, even if the routes are correctly defined, the spec'ed controller seems not to find them.
Something surprises me in the RoutingError: No route matches {:feature=>"feature_models", :controller=>"featuring/features"}. The action => "index" is not displayed.
I had a similar error, and I was also confused by the lack of {:action => "index"} in the route options. However, this turned out not to be the problem. ActionDispatch treats the lack of an :action as equivalent to {:action => "index"}. See:
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/route_set.rb#L545
You may be missing a request parameter in your spec, as was the case with me. Check the Parameters line in your server log when you load the page in the browser.
The trick is to add routes { } to your spec, like so:
describe Featuring::FeaturesController do
routes { Featuring::Engine.routes }
# ...
end
See also No Route Matches ... Rails Engine