ActionController::UrlGenerationError: No route matches - where is my mistake? - ruby-on-rails

This is my test for the chapters controller
require 'test_helper'
class ChaptersControllerTest < ActionController::TestCase
test "should get index_nklm" do
get :index_nklm
assert_response :success
end
test "should get show_nklm" do
get show_chapter_nklm_path(chapters(:one))
assert_response :success
end
end
This is my routes.rb
get 'chapters_nklm' => 'chapters#index_nklm', as: :chapters_nklm
get 'chapter_nklm/:id/show' => 'chapters#show_nklm', as: :show_chapter_nklm
This is my chapters.yml fixture:
one:
id: 12
chapter_name: MyString
chapter: MyString
description: MyText
display: 1
subject_id: 1
This is (part of) the chapters_controller.rb:
def show_nklm
#chapter = Chapter.find(params[:id])
end
And I don't know why I get this error message?
Error:
ChaptersControllerTest#test_should_get_show_nklm:
ActionController::UrlGenerationError: No route matches {:action=>"/chapter_nklm/12/show", :controller=>"chapters"}
test/controllers/chapters_controller_test.rb:11:in `block in <class:ChaptersControllerTest>'
But when I copy "/chapter_nklm/12/show" into the browser, everything works fine? Where is my mistake and which concept didn't I understand?
Thanks in advance!

get is waiting to receive an action as a symbol object, you're passing the whole route alias, plus the object needed.
Try using the params option with your route:
test 'should get show_nklm' do
get :show_nklm, params: { id: chapters(:one).id }
assert_response :success
end

Perhaps you should consider doing something like:
resources :chapters do
get :nklm, to: :show_nklm
end
Which would give you:
chapter_nklm GET /chapters/:chapter_id/nklm(.:format) chapters#show_nklm
chapters GET /chapters(.:format) chapters#index
POST /chapters(.:format) chapters#create
new_chapter GET /chapters/new(.:format) chapters#new
edit_chapter GET /chapters/:id/edit(.:format) chapters#edit
chapter GET /chapters/:id(.:format) chapters#show
PATCH /chapters/:id(.:format) chapters#update
PUT /chapters/:id(.:format) chapters#update
DELETE /chapters/:id(.:format) chapters#destroy
This strikes me as a bit more conventional, and should allow you to do:
class ChaptersControllerTest < ActionController::TestCase
...
test "should get show_nklm" do
get chapter_nklm_path(chapters(:one))
assert_response :success
end
end

Related

How to do Integration Test create through other model

1) I have this model Job and the model institution
class Job < ApplicationRecord
belongs_to :institution
# others attibutes
end
2) This is my action create on JobsController - I need a institution to create a job. it is fine.
def create
build_job
save_job || render(:new, status: :unprocessable_entity)
end
3) This is the integration test that I created
I am not getting the success test
In params
-I also tried institution: #institution
-and also tried institution_id: #institution.id
require 'test_helper'
class JobActionsTest < ActionDispatch::IntegrationTest
setup do
#user = users(:standard)
sign_in #user
#institution = institutions(:standard)
end
test "can create a job through institution" do
get new_institution_job_path(#institution)
assert_response :success
assert_difference('Job.count') do
post jobs_path,
params: {job: {title: "Desenvolvedor", description: "Ruby",
requirements: "rspec and capybara",
start_date: Date.today,
end_date: Date.today + 5.days,
institution: #institution.id}}
end
assert_response :redirect
follow_redirect!
assert_response :success
end
end
4) And this is my console error
#Running:
E
Error:
JobActionsTest#test_can_create_a_job_through_institution:
ActiveRecord::RecordNotFound: Couldn't find Institution with 'id'=
app/controllers/jobs_controller.rb:74:in `job_scope'
app/controllers/jobs_controller.rb:52:in `build_job'
app/controllers/jobs_controller.rb:18:in `create'
test/integration/job_actions_test.rb:22:in `block (2 levels) in <class:JobActionsTest>'
test/integration/job_actions_test.rb:21:in `block in <class:JobActionsTest>'
bin/rails test test/integration/job_actions_test.rb:17
Start by nesting the jobs resource properly:
resources :institutions do
resources :jobs, only: [:new, :create]
end
# or to create the full suite
resources :institutions do
resources :jobs, shallow: true
end
This will give these routes:
Prefix Verb URI Pattern Controller#Action
institution_jobs POST /institutions/:institution_id/jobs(.:format) jobs#create
new_institution_job GET /institutions/:institution_id/jobs/new(.:format) jobs#new
...
Note that :institution_id is a now a part of URI pattern for the create route, and it will be available as params[:institution_id].
In your test you want to POST to /institutions/:institution_id/jobs:
require 'test_helper'
class JobActionsTest < ActionDispatch::IntegrationTest
setup do
#user = users(:standard)
sign_in #user
#institution = institutions(:standard)
end
# Use separate examples per route / case
test "can fill in form to create a new job" do
get new_institution_job_path(#institution)
assert_response :success
end
test "can create a job through institution" do
assert_difference ->{ #institution.jobs.count } do
post institution_jobs_path(#institution),
params: {
job: {
title: "Desenvolvedor",
description: "Ruby",
requirements: "rspec and capybara",
start_date: Date.today,
end_date: Date.today + 5.days
}
}
end
assert_redirected_to #institution.jobs.last
follow_redirect!
assert_response :success
end
end
Further you want to test that the job actually was created for the right institution. We do that by passing the lambda ->{ #institution.jobs.count }.
And that the users are redirected to the correct resource - not just somewhere - which is done with assert_redirected_to #institution.jobs.last.
It looks like that when you call at line 22
get new_institution_job_path(#institution)
the #institution object you have built in the setup block is not saved in the database.
The error you are receiving, ActiveRecord::RecordNotFound, says that it cannot be found an Institution with id nil.
You can easily check if I am guessing correctly by adding this assertion:
test "can create a job through institution" do
assert_not_nil(#institution.id) # or assert_not_equal(0, Institution.where(id: #institution.id).size)
get new_institution_job_path(#institution)
assert_response :success
#...
end
Make sure that your institutions(:standard) method looks like Institution.create!() and not like Institution.new or Institution.build

Controll spec ActionController::UrlGenerationError

I've got routes setup so that they work as expected in my controllers; I can use both room_path and rooms_path as expected.
However when I try to use the same routes in a controller spec for some reason then I get an error:
ActionController::UrlGenerationError:
No route matches {:action=>"/1", :controller=>"rooms"}
My routes.rb file:
root "rooms#index"
resources :rooms, :path => '/', only: [:index, :create, :show] do
resources :connections, only: [:create,:destroy]
end
And if I rake routes:
room_connections POST /:room_id/connections(.:format) connections#create
room_connection DELETE /:room_id/connections/:id(.:format) connections#destroy
rooms GET / rooms#index
POST / rooms#create
room GET /:id(.:format) rooms#show
However my test fails:
describe "GET room_path(room)" do
it "renders show" do
#room = Room.create
get room_path(#room)
expect(response.status).to eq(200)
expect(response).to render_template(:show)
end
end
While my controllers can use the same route helpers without issue:
class RoomsController < ApplicationController
def index
end
def create
#room = Room.create
redirect_to room_path(#room)
end
def show
#room = Room.find(params[:id])
end
end
I'm not sure why in my tests it seems to go looking for a "/1" action rather than rooms#show like I would expect.
Update
So continuing to play this I've been able to get the test green by changing to the following:
describe "GET room_path(room)" do
it "renders show" do
#room = Room.create
get :show, params: { id: #room.id }
expect(response.status).to eq(200)
expect(response).to render_template(:show)
end
end
I would still love to understand why my helpers aren't working though. Is this to be expected? Manually writing the Parameters hash is kind of a PITA.
I don't know what version of Rails and RSpec you're on. This works for me on Rails 4.2 and Rspec 3.4.4:
describe "my neat test description", type: :routing do
it "can use path helper" do
puts whatever_path
end
end
The type: :routing pulls in the path and url helpers.
I believe the reason you don't have that by default is that rspec is replicating a lot of the environment for the different types of tests. For controller tests, it's pulling in the various path and url helpers because generally speaking they're used there often enough to be worth pulling in. In model tests, for example, they aren't used there often so they aren't pulled in by default.
These helpers live on the app object.

'No route matches' error while using Factory Girl on Rails

I've been trying to use FactoryGirl for tests on my Rails application, but I'm running into difficulty with it.
I feel as if there must be something fairly obvious I'm doing wrong, but after much searching I haven't been able to figure out the cause.
I'm trying to run a test to confirm the 'show' action is successful on one of my controllers.
Here's the error message I'm getting:
Failure/Error: get 'show'
ActionController::UrlGenerationError:
No route matches {:action=>"show", :controller=>"simple_requests"}
Below are the relevant code snippets leading to this outcome.
/spec/controllers/simple_requests_controller_spec.rb
require 'spec_helper'
describe SimpleRequestsController do
describe "GET 'show'" do
before do
#simple_request = build(:simple_request)
end
it "should be successful" do
get 'show'
expect(response).to be_success
end
end
end
/factories/simple_requests_controller_spec.rb
FactoryGirl.define do
factory :simple_request do
id 123
full_name "Testie McTesterson"
company "Test Company"
role "Analyst"
email "foobar#foobs.com"
phone "000888"
message "Test question?"
end
end
/controllers/simple_requests_controller.rb
def show
authorize SimpleRequest #For pundit
#simple_request = SimpleRequest.find(params[:id])
end
I have two hypotheses as to why this may be happening:
1) Rspec is looking for an id for the 'show' action, but somehow can't find it. (Although there is one in the Factory, and I've yet to figure out how it wouldn't be flowing through.)
2) Pundit is causing issues, since the show action may require authorization (although commenting out the 'authorize' line makes no difference at present)
Any and all thoughts welcome :)
EDIT
Pasting below the output of rake routes | grep simple_requests
simple_requests GET /simple_requests(.:format) simple_requests#index
POST /simple_requests(.:format) simple_requests#create
new_simple_request GET /simple_requests/new(.:format) simple_requests#new
edit_simple_request GET /simple_requests/:id/edit(.:format) simple_requests#edit
simple_request GET /simple_requests/:id(.:format) simple_requests#show
PATCH /simple_requests/:id(.:format) simple_requests#update
PUT /simple_requests/:id(.:format) simple_requests#update
DELETE /simple_requests/:id(.:format) simple_requests#destroy
Edit 2 - Adding ID parameter
I have now also attempted to add an id as follows:
it "should be successful" do
get 'show', id: #simple_request.id
expect(response).to be_success
end
This time I received the following error message
ActiveRecord::RecordNotFound: Couldn't find SimpleRequest with 'id'=123
'123' is the ID in my /factories - I think I must be missing something to get this working, but can't figure out what yet.
Your SimpleRequest does not have an Id. You need to use create instead of build
before do
#simple_request = create(:simple_request)
end
it "should be successful" do
get 'show', id: #simple_request.id
expect(response).to be_success
end
Try this:
before do
#simple_request = create :simple_request
end
it "should be successful" do
get 'show', id: #simple_request.id
expect(response).to be_success
end
It's a show view, so you'll have to supply your request with an ID and you'll have to actually create a record with create instead of build in your before block.

Rspec: how do I test for a redirect?

I've got some routes that look like this:
constraints ClientCodeConstraint.new do
get 'share/:client_code', to: redirect('/%{client_code}')
get 'share/:client_code/:id', to: redirect('/%{client_code}/%{id}')
get ':client_code', to: 'share#index', as: :shares
get ':client_code/:id', to: 'share#show', as: :share
get ':client_code/:document_id/more/:component_id', to: 'share#more', as: :more
end
My constraint looks like this:
class ClientCodeConstraint
def matches?(request)
users.each do |user|
return true if request.path_parameters[:client_code] == user.client_code
end
end
def users
#users ||= User.all
end
end
I've got tests like this but I'm having no luck:
context 'not logged in' do
let!(:user) { create(:user) }
let!(:document) { create(:document) }
specify 'renders the :index view' do
get :index
expect(response.code).to eq '302'
expect(response).to redirect_to("/#{assigns(:user).client_code}")
end
specify 'renders the :show view' do
get :show
expect(response).to redirect_to("/#{assigns(:user).client_code}/#{assigns(:document).id}")
end
end
How do I test with Rspec these redirects? I just get a bunch of these errors:
ActionController::RoutingError: No route matches {:controller=>"share"}
And the controller and routes of course exist.
UPDATE
Relevant rake routes output is here:
GET /share/:client_code(.:format) :controller#:action
GET /share/:client_code/:id(.:format) :controller#:action
shares GET /:client_code(.:format) share#index
share GET /:client_code/:id(.:format) share#show
more GET /:client_code/:document_id/more/:component_id(.:format) share#more
The tests pass like this:
specify 'renders the :index view' do
get :index, client_code: user.client_code
expect(response.status).to eq(200)
end
That feels though like I'm testing only that the response is correct. I want to test more thoroughly, i.e., it doesn't render an error message, etc.

RSpec Controller Test not generating right url

I am attempting to create a RSpec controller test for a namespaced controller, but rspec doesn't seem able to detect the nesting and generate the proper path for the post :create action.
This is my spec code:
# for: /app/controllers/admin/crm/report_adjustments_controller.rb
require 'spec_helper'
describe Admin::Crm::ReportAdjustmentsController do
render_views
before(:each) do
signin
end
describe "GET 'index'" do
it "returns http success" do
get :index
response.should be_success
end
end
describe "POST 'create'" do
it "creates with right parameters" do
expect {
post :create, report_adjustment: {distributor_id: #ole_distributor.id, amount: "30.0", date: Date.today }
}.to change(Crm::ReportAdjustment, :count).by(1)
response.should be_success
end
end
end
# routes.rb
namespace :admin do
namespace :crm do
resources :report_adjustments
end
end
For this code, the get :index works just fine, but when post :create is called, the following error is generated: undefined method 'crm_report_adjustment_url'
Why would RSpec be smart enough to figure things out with get :index, but not with post :create? How do I get RSpec to properly load the right route, which is admin_crm_report_adjustments_url?
Thanks in advance.
Try posting to the url instead:
post admin_crm_report_adjustments_url
# or
post "/admin/crm/report_adjustments"

Resources