How to test that a route does not work? - ruby-on-rails

How can I negate the following test?
test "should route to post" do
post = posts(:one)
assert_routing "/posts/#{post.id}", {
controller: "posts",
action: "show",
id: "#{post.id}"
}
end
I want to test that the route /posts/1 does not exist.

This should work. This will test if the route for :new exists (might be overkill)
$> route.defaults #outputs: {:controller=>"posts", :action=>"index"}
test "shouldn't have route new" do
admin_routes = Rails.application.routes.routes.
select { |route| route.path.spec.to_s.starts_with? "/posts" }
admin_routes.each do |route|
assert_not route.defaults[:action].
include?('new'), "route :new is not allow to exist"
end
end

The only thing I can come up with is try the route and then assert an exception will be raised:
test "should route to post" do
post = posts(:one)
assert_raises Minitest::Assertion do
assert_routing "/posts/#{post.id}"
end
end
Or
assert_raises ActionController::UrlGenerationError do
get "/users/1"
end
But I don't like either of those to be honest.

Related

ActionController::UrlGenerationError: No route matches {:action=>"/users/762146111"

I've been following the Michael Hartl tutorial for learning rails and have been doing pretty well thus far, but I'm stumped on this issue which I've encountered repeatedly. I'm not skilled enough to know if there is a configuration problem in my environment or something else, but this makes NO sense to me.
In ANY of the controller tests I attempt to run, I can never get my helper URL methods to work. As an example:
test "should redirect home when not an admin" do
log_in_as(#other_user)
assert_no_difference 'User.count' do
delete user_path(#user)
end
assert redirect_to root_url
end
Generates the following error:
ERROR["test_should_redirect_home_when_not_an_admin", UsersControllerTest, 0.9899668790167198]
test_should_redirect_home_when_not_an_admin#UsersControllerTest (0.99s)
ActionController::UrlGenerationError: ActionController::UrlGenerationError: No route matches {:action=>"/users/762146111", :controller=>"users"}
test/controllers/users_controller_test.rb:60:in `block (2 levels) in <class:UsersControllerTest>'
test/controllers/users_controller_test.rb:59:in `block in <class:UsersControllerTest>'
Even simple tests like
test "should redirect index when not logged in" do
get users_path
assert_redirected_to login_url
end
Produce the same error:
ERROR["test_should_redirect_index_when_not_logged_in", UsersControllerTest, 1.5291320629185066]
test_should_redirect_index_when_not_logged_in#UsersControllerTest (1.53s)
ActionController::UrlGenerationError: ActionController::UrlGenerationError: No route matches {:action=>"/users", :controller=>"users"}
test/controllers/users_controller_test.rb:34:in `block in <class:UsersControllerTest>'
Everything I've googled about this issue hasn't helped, because for some reason I cannot determine the user_path method (or any other similar method) somehow thinks the action I'm trying to take in my controller is the path!
I've verified that my routes file is configured correctly.
Rails.application.routes.draw do
root 'static_pages#home'
get '/help' => 'static_pages#help'
get '/about' => 'static_pages#about'
get '/contact' => 'static_pages#contact'
get '/signup' => 'users#new'
post '/signup' => 'users#create'
get '/login' => 'sessions#new'
post '/login' => 'sessions#create'
delete '/logout' => 'sessions#destroy'
get 'sessions/new'
resources :users
end
I've checked that running "rails routes" has the correct routes. I've even checked in rails console that "app.user_path(1)" spits out a valid path.
At this point I'm just beyond stumped as to why these helper methods don't seem to be helping... I also don't know what they're actually called so my googling has been fairly fruitless.
To get around this issue in the tutorial, I've been using syntax like
patch :edit, { id: #user }, params: { user: { name: #user.name,
email: #user.email }}
Or
test "should redirect index when not logged in" do
get :index
assert_redirected_to login_url
end
Which seems to work.
Also here is one of my test files if that's helpful:
require 'test_helper'
class UsersControllerTest < ActionController::TestCase
def setup
#user = users(:michael)
#other_user = users(:archer)
end
test "should get new" do
get :new
assert_response :success
end
test "should redirect edit when user not logged in" do
get :edit, params: { id: #user }
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect update when user not logged in" do
patch :edit, { id: #user }, params: { user: { name: #user.name,
email: #user.email }}
assert_not flash.empty?
assert_redirected_to login_url
end
test "should redirect index when not logged in" do
# get users_path
get :index
assert_redirected_to login_url
end
test "should redirect destroy when not logged in" do
assert_no_difference 'User.count' do
delete user_path(#user)
end
assert redirect_to login_url
end
test "should redirect home when not an admin" do
log_in_as(#other_user)
assert_no_difference 'User.count' do
delete user_path(#user)
end
assert redirect_to root_url
end
end
Please let me know what other files I can post to be helpful.
I had the same issue and I fixed it by changing the file 'users_controller_test.rb' file replacing:
class UsersControllerTest < ActionController::TestCase
for
class UsersControllerTest < ActionDispatch::IntegrationTest
But first, in your case, check that you have in your Gemfile the line:
gem 'rails', '5.0.1'
as the tutorial shows.
I can also see that you have the following test:
test 'should get new' do
get :new
assert_response :success
end
When you make the correction you'll have to change the above test to:
test 'should get new' do
get new_user_path
assert_response :success
end
After that, run your tests and you should have them all passed.
Hope it helps

Strange behavior of assert_redirected_to method

I have the following code:
it 'should create' do
post :create, investor: VALID_CREATE_PARAMS
expect(response).to redirect_to(controller: 'admin/investors', action: 'show')
end
It generates following error:
1) Admin::InvestorsController create should create
Failure/Error: expect(response).to redirect_to(controller: 'admin/investors', action: 'show')
ActionController::UrlGenerationError:
No route matches {:action=>"show", :controller=>"admin/investors"}
The routes are
namespace :admin do
resources :investors
end
How can I fix this issue? I have no option to assert redirection with admin_investor_path, because I keep url params while redirecting.
Show action by default requires an id to be passed as well, without the id it can't generate the url
You need to add it like this:
expect(response).to redirect_to(controller: 'admin/investors', action: 'show', id: assigns(:investor).id )

New Controller - No Route Matches update, edit, show or destroy

I'm having some difficulty getting all the RESTful routes to be setup correctly. I've taken the simplest of simple steps in my app so far.
Create new rails app
Create new controller with RESTful actions
Add resources to routes.rb
And yet 4 out of my 7 actions fail the default tests. Can anyone please explain why?
rails generate controller Employees new create update edit destroy index show
And here's the corresponding controller, employees_controller.rb
class EmployeesController < ApplicationController
def new
end
def create
end
def update
end
def edit
end
def destroy
end
def index
end
def show
end
end
Now I add the resources to routes.rb
Rails.application.routes.draw do
resources :employees
end
All the routes seem to be there, based on the output of rake routes
Prefix Verb URI Pattern Controller#Action
employees GET /employees(.:format) employees#index
POST /employees(.:format) employees#create
new_employee GET /employees/new(.:format) employees#new
edit_employee GET /employees/:id/edit(.:format) employees#edit
employee GET /employees/:id(.:format) employees#show
PATCH /employees/:id(.:format) employees#update
PUT /employees/:id(.:format) employees#update
DELETE /employees/:id(.:format) employees#destroy
But now when I run the default tests, I get 4 errors:
# Running:
.EEEE..
Finished in 0.267712s, 26.1475 runs/s, 11.2061 assertions/s.
1) Error:
EmployeesControllerTest#test_should_get_update:
ActionController::UrlGenerationError: No route matches {:action=>"update", :controller=>"employees"}
test/controllers/employees_controller_test.rb:15:in `block in <class:EmployeesControllerTest>'
2) Error:
EmployeesControllerTest#test_should_get_destroy:
ActionController::UrlGenerationError: No route matches {:action=>"destroy", :controller=>"employees"}
test/controllers/employees_controller_test.rb:25:in `block in <class:EmployeesControllerTest>'
3) Error:
EmployeesControllerTest#test_should_get_show:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"employees"}
test/controllers/employees_controller_test.rb:35:in `block in <class:EmployeesControllerTest>'
4) Error:
EmployeesControllerTest#test_should_get_edit:
ActionController::UrlGenerationError: No route matches {:action=>"edit", :controller=>"employees"}
test/controllers/employees_controller_test.rb:20:in `block in <class:EmployeesControllerTest>'
7 runs, 3 assertions, 0 failures, 4 errors, 0 skips
Lastly, here is the contents of employees_controller_test.rb. As I said, these are the default tests auto-created by Rails upon generation of the controller.
require 'test_helper'
class EmployeesControllerTest < ActionController::TestCase
test "should get new" do
get :new
assert_response :success
end
test "should get create" do
get :create
assert_response :success
end
test "should get update" do
get :update
assert_response :success
end
test "should get edit" do
get :edit
assert_response :success
end
test "should get destroy" do
get :destroy
assert_response :success
end
test "should get index" do
get :index
assert_response :success
end
test "should get show" do
get :show
assert_response :success
end
end
according to dimakura's answer you have to change some routes in your test
the update method is a put (or a patch for partial changes in rails4)
test "should get update" do
put :update
assert_response :success
end
and for your edit, delete and show routes, the id is missing
test "should get edit" do
get :edit, id: 2
assert_response :success
end
Your controller test probably looks like:
class EmployeesControllerTest < ActionController::TestCase
test "should get create" do
get :create
assert_response :success
end
# other tests not shown
end
You should change it to this:
class EmployeesControllerTest < ActionController::TestCase
test "should get create" do
post :create
assert_response :success
end
# other tests should be changed accordingly
end
Use patch or put method for update, and delete for delete actions.

ActionController::UrlGenerationError - with route defined and action in controller, still getting error for no route

I'm getting the following error in RSpec when running my schools_controller_spec.rb test:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"schools"}
What's puzzling me is that I have the routes configured, and the action defined in the appropriate controller. I'm not getting this error for other tests in the spec, such as 'GET #index', etc. Running Rails 4.2 with RSpec/Capybara.
Here's the routes.rb:
Rails.application.routes.draw do
root to: 'pages#home', id: 'home'
resources :users
resources :schools
resource :session, only: [:new, :create, :destroy]
match '/home', to: 'pages#home', via: 'get', as: 'home_page'
end
rake routes returns:
schools GET /schools(.:format) schools#index
POST /schools(.:format) schools#create
new_school GET /schools/new(.:format) schools#new
edit_school GET /schools/:id/edit(.:format) schools#edit
school GET /schools/:id(.:format) schools#show
PATCH /schools/:id(.:format) schools#update
PUT /schools/:id(.:format) schools#update
DELETE /schools/:id(.:format) schools#destroy
There's the route defined on the fifth line, as schools#show.
The schools_controller.rb:
class SchoolsController < ApplicationController
before_action :require_signin
before_filter :admin_only, except: :index, :show
def index
#schools = School.all
end
def show
# code pending
end
private
def admin_only
unless current_user.admin?
redirect_to :back, alert: "Access denied."
end
end
end
The link to the individual school seems to be properly defined in the view helper (_school.html.haml):
%li#schools
= link_to school.name, school
= school.short_name
= school.city
= school.state
and looking at the front-end HTML confirms it's working correctly. I can see, for example: Community College of the Air Force. When I click that link the page shows the following in the debug dump:
--- !ruby/hash:ActionController::Parameters
controller: schools
action: show
id: '1'
Finally, for good measure, here's the spec file (schools_controller_spec.rb):
require 'rails_helper'
describe SchoolsController, type: :controller do
# specs omitted for other actions
describe 'GET #show' do
context "when not signed in" do
it "returns a 302 redirect code" do
get :show
expect(response.status).to eq 302
end
it "redirects to the signin page" do
get :show
expect(response).to redirect_to new_session_path
end
end
context "when signed in as user" do
before :each do
#user = double(:user)
allow(controller).to receive(:current_user).and_return #user
#school = create(:school)
end
it "assigns the school to the #school variable" do
get :show
expect(assigns(:school)).to eq #school
end
end
end
end
The route appears in rake routes. The method is defined in the appropriate controller. There don't appear to be any silly naming errors (e.g. plural/singular). The spec doesn't appear to have any issues routing GET #index or other routes for example. Everything works exactly as expected in the browser.
So why do I keep getting the "no route matches" error when I run my controller spec?
This is because the show action is expecting an id which you currently aren't passing. Replace:
get :show
With this:
get :show, id: school.id
The above assumes you have a school variable, perhaps a let in a before block?
let(:school) { create(:school) }

test_should_get_show(CartsControllerTest): ActionController::RoutingError: No route matches {:cart=>"1", :controller=>"carts", :action=>"show"}

The error I keep getting is as follows:
test_should_get_show(CartsControllerTest):
ActionController::RoutingError: No route matches {:cart=>"1", :controller=>"carts", :action=>"show"}
When I run the following code:
def setup
#cart = FactoryGirl.create(:cart)
end
test "should get show" do
sign_in(FactoryGirl.create(:user, admin: true))
session[:cart_id] = #cart.id
get :show, cart: #cart
assert_response :success
assert_not_nil assigns(:product_requests)
end
My cart factory:
FactoryGirl.define do
factory :cart do
factory :cart_with_1_row do
after(:create) do |cart|
FactoryGirl.create(:cart_row, cart: cart)
end
end
end
end
However, in my rake routes I have:
cart GET /carts/:id(.:format) carts#show
I can also go to http://localhost:3000/carts/1 manually in the browser in the development environment and it works fine.
What could be causing this?
Replace:
get :show, cart: #cart
With:
get :show, id: #cart # or #cart.id

Resources