Problem with routes in functional testing - ruby-on-rails

I'm making a simple test project to prepare myself for my test.
I'm fairly new to nested resources, in my example I have a newsitem and each newsitem has comments.
The routing looks like this:
resources :comments
resources :newsitems do
resources :comments
end
I'm setting up the functional tests for comments at the moment and I ran into some problems.
This will get the index of the comments of a newsitem. #newsitem is declared in the setup ofc.
test "should get index" do
get :index,:newsitem_id => #newsitem
assert_response :success
assert_not_nil assigns(:newsitem)
end
But the problem lays here, in the "should get new".
test "should get new" do
get new_newsitem_comment_path(#newsitem)
assert_response :success
end
I'm getting the following error.
ActionController::RoutingError: No route matches {:controller=>"comments", :action=>"/newsitems/1/comments/new"}
But when I look into the routes table, I see this:
new_newsitem_comment GET /newsitems/:newsitem_id/comments/new(.:format) {:action=>"new", :controller=>"comments"}
Can't I use the name path or what I'm doing wrong here?
Thanks in advance.

The problem is in the way your test specifies the URL. The error message is:
No route matches {:controller=>"comments", :action=>"/newsitems/1/comments/new"}
and of course there is no action called "/newsitems/1/comments/new". You want to pass the hash { :controller => :comments, :action => :new, :news_item_id => 1 }.
The right syntax is simply:
get :new, :news_item_id => 1

(Assuming Rails 3)
Try this in your routes.rb
GET 'newsitems/:newsitem_id/comments/new(.:format)' => 'comments#new', :as => :new_newsitem_comment

Related

Rspec not finding routes that exists

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'

Routes on Rails application are failing

I'm taking an MOOC and the goal of this exercise is to add a new functionality to typo, where i can merge two articles together.
When I add the route to my new function merge to the routes.rb I'm losing the functionality to delete articles. I think something clashes here, but I have no idea what.
The original routes.rb:
%w{advanced cache categories comments content profiles feedback general pages
resources sidebar textfilters themes trackbacks users settings tags redirects seo post_types }.each do |i|
match "/admin/#{i}", :to => "admin/#{i}#index", :format => false
match "/admin/#{i}(/:action(/:id))", :to => "admin/#{i}", :action => nil, :id => nil, :format => false
end
This method in articles.rb creates the correct url for deleting
def delete_url
blog.url_for(:controller => "/admin/content", :action =>"destroy",:id => id)
end
correct url:
http://example.com/admin/content/destroy/7
If i follow this link i can successfully delete an article.
However, if I add the following before that to my routes.rb:
namespace "admin" do
resources :content do
post :merge, on: :member, as: :merge
end
end
The new merging functionality and forms are working fine, but the method delete_url now produces something like this:
http://example.com/admin/content/7
and if I follow a link created by this method i get:
Unknown action
The action 'show' could not be found for Admin::ContentController
Maybe I'm overwriting something? I can't figure out what's happening here and why this affects the delete action / route.
Thanks in advance!
EDIT: rake routes | grep content:
with the original routes.rb gives me:
admin_content /admin/content {:controller=>"admin/content", :action=>"index"}
/admin/content(/:action(/:id)) {:action=>nil, :id=>nil, :controller=>"admin/content"}
whereas my modified routes.rb produces
merge_admin_content POST /admin/content/:id/merge(.:format) {:action=>"merge", :controller=>"admin/content"}
admin_content_index GET /admin/content(.:format) {:action=>"index", :controller=>"admin/content"}
POST /admin/content(.:format) {:action=>"create", :controller=>"admin/content"}
new_admin_content GET /admin/content/new(.:format) {:action=>"new", :controller=>"admin/content"}
edit_admin_content GET /admin/content/:id/edit(.:format) {:action=>"edit", :controller=>"admin/content"}
admin_content GET /admin/content/:id(.:format) {:action=>"show", :controller=>"admin/content"}
PUT /admin/content/:id(.:format) {:action=>"update", :controller=>"admin/content"}
DELETE /admin/content/:id(.:format) {:action=>"destroy", :controller=>"admin/content"}
/admin/content {:controller=>"admin/content", :action=>"index"}
/admin/content(/:action(/:id)) {:action=>nil, :id=>nil, :controller=>"admin/content"}
Okay, thanks to #guitarman i worked through my routes code and found out I can add the following except:
namespace "admin" do
resources :content, except: [:index, :show, :update, :destroy, :edit, :new, :create] do
post :merge, on: :member, as: :merge
end
end
after that, the rake routes just shows the additional merge route I wanted and my destroy action works fine again.
Check rake routes command. I think there is a route /admin/content/:id which will be created by resources :content in the namespace "admin".
Your request to http://example.com/admin/content/7 will be catched be the defined route but I gess you have no show action in the controller.
Better:
namespace "admin" do
post "/content/:id/merge", to: "admin/content#merge", as: :merge
end
For more information about recources and the CRUD operations please see the rails routing guide.

All get/put calls error w/"no route matches" in rspec tests; though they work fine in app

Routes that work fine in my application fail on any get/put call in rspec testing with 'No route matches'. What am I doing wrong here?
Here's a simple example, from contracts_controller_spec.rb:
it 'should redirect to edit on show' do
get :show
response.should be_success
response.should render_template(:edit)
end
The above fails with the following:
ContractsController api calls should redirect to edit on show
Failure/Error: get :show
ActionController::RoutingError:
No route matches {:controller=>"contracts", :action=>"show"}
the show method in contracts_controller.rb:
def show
Rails.logger.debug("getting contract info....")
get_contract_info
Rails.logger.debug("...got contract info.")
render :action => :edit
end
routes.rb content:
resource :contract, :only=>[:show, :edit, :update], :protocol =>ROUTES_PROTOCOL do
member do
get :print
end
end
rake routes output:
print_contract GET /contract/print(.:format) contracts#print {:protocol=>"http"}
edit_contract GET /contract/edit(.:format) contracts#edit {:protocol=>"http"}
contract GET /contract(.:format) contracts#show {:protocol=>"http"}
PUT /contract(.:format) contracts#update {:protocol=>"http"}
using rspec-rails 2.14.0
This app was recently upgraded from Rails 2.3 to 3.2, which has otherwise been successful
note the non-standard show/edit routes: no id is required, and forcing an id still results in No route matches {:controller=>"contracts", :id=>"1", :action=>"show"}
:protocol is bit weird, try to remove ??

Rails custom route not found when testing, but works for curl

In config/routes.rb:
match 'app_config/:version' => "application#appconfig"
test/functional/application_controller_test.rb:
require 'test_helper'
class ApplicationControllerTest < ActionController::TestCase
test "app config" do
get "/app_config/v2"
assert_response :success
end
end
rake test:
1) Error:
test_app_config(ApplicationControllerTest):
ActionController::RoutingError: No route matches {:controller=>"application", :action=>"/app_config/v2"}
but $ curl localhost:3000/app_config/v2 works, and returns the response I expect, and rake routes shows the route as expected. Any idea what's going on, or how to investigate further? This is basically the only code in the project.
The get method does not take a route. It takes an action name and a parameter's hash.
If you want to test the action, your tests should look like this:
test "for success" do
get :appconfig, :version => "v2"
assert_response :success
end
If you want to test routing there is a tutorial here in the documentation.
test "should route to appconfig" do
assert_routing '/app_config/v2', { :controller => "application", :action => "appconfig", :version => "v2" }
end

Route works in browser, fails in Rspec

This question has probably been asked a dozen times on Stack Overflow (e.g. (1), (2), (3), (4), (5)) but every time the answer seems to be different and none of them have helped me. I'm working on a Rails Engine and I'm finding that Rspec2 gets route errors, but I can reach the routes in the browser. Here's the situation:
In the engine's routes.rb:
resources :mw_interactives, :controller => 'mw_interactives', :constraints => { :id => /\d+/ }, :except => :show
# This is so we can build the InteractiveItem at the same time as the Interactive
resources :pages, :controller => 'interactive_pages', :constraints => { :id => /\d+/ }, :only => [:show] do
resources :mw_interactives, :controller => 'mw_interactives', :constraints => { :id => /\d+/ }, :except => :show
end
Excerpted output of rake routes:
new_mw_interactive GET /mw_interactives/new(.:format) lightweight/mw_interactives#new {:id=>/\d+/}
...
new_page_mw_interactive GET /pages/:page_id/mw_interactives/new(.:format) lightweight/mw_interactives#new {:id=>/\d+/, :page_id=>/\d+/}
And my test, from one of the controller specs (describe Lightweight::MwInteractivesController do):
it 'shows a form for a new interactive' do
get :new
end
...which gets this result:
Failure/Error: get :new
ActionController::RoutingError:
No route matches {:controller=>"lightweight/mw_interactives", :action=>"new"}
...and yet when I go to that route in the browser, it works exactly as intended.
What am I missing here?
ETA: To clarify a point Andreas raises: this is a Rails Engine, so rspec runs in a dummy application which includes the engine's routes in a namespace:
mount Lightweight::Engine => "/lightweight"
...so the routes shown in rake routes are prefaced with /lightweight/. That's why the route shown in the Rspec error doesn't seem to match what's in rake routes. But it does make the debugging an extra step wonkier.
ETA2: Answering Ryan Clark's comment, this is the action I'm testing:
module Lightweight
class MwInteractivesController < ApplicationController
def new
create
end
...and that's it.
I found a workaround for this. Right at the top of the spec, I added this code:
render_views
before do
# work around bug in routing testing
#routes = Lightweight::Engine.routes
end
...and now the spec runs without the routing error. But I don't know why this works, so if someone can post an answer which explains it, I'll accept that.
I think the might be something wrong higher up in you specs
how did the "lightweight" get into this line :controller=>"lightweight/mw_interactives"
the route says
new_mw_interactive GET /mw_interactives/new(.:format)
not
new_mw_interactive GET /lightweight/mw_interactives/new(.:format)
add a file spec/routing/root_routing_spec.rb
require "spec_helper"
describe "routes for Widgets" do
it "routes /widgets to the widgets controller" do
{ :get => "/" }.should route_to(:controller => "home", :action => "index")
end
end
then add a file spec/controllers/home_controller_spec.rb
require 'spec_helper'
describe HomeController do
context "GET index" do
before(:each) do
get :index
end
it {should respond_with :success }
it {should render_template(:index) }
end
end

Resources