I have this RSpec test:
# /spec/controllers/user/builder_tab/biographies_controller_spec.rb
describe User::BuilderTab::BiographiesController do
before(:each) do
#user = create :user
sign_in #user
end
describe "#update" do
it "can update" do
patch :update, profile: { name: "Joe Peshi" }
expect(User.first.profile.name).to eq "Joe Peshi"
end
end
end
But when I run it - for some reason it makes this request:
No route matches {:profile=>{:name=>"Joe Peshi"}, :controller=>"user/biographies", :action=>"update"}
Which obviously fails because the path is not /user/biographies - it's /user/builder_tab/biographies.
How do I fix it?
My routes are:
namespace :user do
namespace :builder_tab do
resource :biography, only: [:edit, :update]
end
end
Builder_tab is defined like so:
class User::BuilderTab < User
end
try to be verbose with your modules and see if it helps
module User
module BuilderTab
describe BiographiesController
..
end
end
end
Related
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
I'm learning RSpec by writing specs for an existing project. I'm having trouble with a controller spec for a polymorphic resource Notes. Virtually any other model can have a relationship with Notes like this: has_many :notes, as: :noteable
In addition, the app is multi-tenant, where each Account can have many Users. Each Account is accessed by :slug instead of :id in the URL. So my mulit-tenant, polymorphic routing looks like this:
# config/routes.rb
...
scope ':slug', module: 'accounts' do
...
resources :customers do
resources :notes
end
resources :products do
resources :notes
end
end
This results in routes like this for the :new action
new_customer_note GET /:slug/customers/:customer_id/notes/new(.:format) accounts/notes#new
new_product_note GET /:slug/products/:product_id/notes/new(.:format) accounts/notes#new
Now on to the testing problem. First, here's an example of how I test other non-polymorphic controllers, like invitations_controller:
# from spec/controllers/accounts/invitation_controller_spec.rb
require 'rails_helper'
describe Accounts::InvitationsController do
describe 'creating and sending invitation' do
before :each do
#owner = create(:user)
sign_in #owner
#account = create(:account, owner: #owner)
end
describe 'GET #new' do
it "assigns a new Invitation to #invitation" do
get :new, slug: #account.slug
expect(assigns(:invitation)).to be_a_new(Invitation)
end
end
...
end
When i try to use a similar approach to test the polymorphic notes_controller, I get confused :-)
# from spec/controllers/accounts/notes_controller_spec.rb
require 'rails_helper'
describe Accounts::NotesController do
before :each do
#owner = create(:user)
sign_in #owner
#account = create(:account, owner: #owner)
#noteable = create(:customer, account: #account)
end
describe 'GET #new' do
it 'assigns a new note to #note for the noteable object' do
get :new, slug: #account.slug, noteable: #noteable # no idea how to fix this :-)
expect(:note).to be_a_new(:note)
end
end
end
Here I'm just creating a Customer as #noteable in the before block, but it could just as well have been a Product. When I run rspec, I get this error:
No route matches {:action=>"new", :controller=>"accounts/notes", :noteable=>"1", :slug=>"nicolaswisozk"}
I see what the problem is, but i just can't figure out how to address the dynamic parts of the URL, like /products/ or /customers/.
Any help is appreciated :-)
UPDATE:
Changed the get :new line as requested below to
get :new, slug: #account.slug, customer_id: #noteable
and this causes the error
Failure/Error: expect(:note).to be_a_new(:note)
TypeError:
class or module required
# ./spec/controllers/accounts/notes_controller_spec.rb:16:in `block (3 levels) in <top (required)>'
Line 16 in the spec is:
expect(:note).to be_a_new(:note)
Could this be because the :new action in my notes_controller.rb is not just a #note = Note.new, but is initializing a new Note on a #noteable, like this?:
def new
#noteable = find_noteable
#note = #noteable.notes.new
end
Well the problem here should be that in this line
get :new, slug: #account.slug, noteable: #noteable
you are passing :noteable in params. But, you need to pass all the dynamic parts of the url instead to help rails match the routes. Here you need to pass :customer_id in params. Like this,
get :new, slug: #account.slug, customer_id: #noteable.id
Please let me know if this helps.
I'm trying to write a controller test which tests a subdomain constraint. However, I'm unable to get RSpec to set the subdomain and return an error if the subdomain isn't accurate.
I'm using Rails 4.2.6 and RSpec ~3.4
routes.rb
namespace :frontend_api do
constraints subdomain: 'frontend-api' do
resources :events, only: [:index]
end
end
events_controller.rb
module FrontendAPI
class EventsController < FrontendAPI::BaseController
def index
render json: []
end
end
end
spec
RSpec.describe FrontendAPI::EventsController do
describe 'GET #index' do
context 'wrong subdomain' do
before do
#request.host = 'foo.example.com'
end
it 'responds with 404' do
get :index
expect(response).to have_http_status(:not_found)
end
end
end
end
Is there some other way of doing this?
You can accomplish this by using the full URL in your tests instead of setting the host in a before block.
Try:
RSpec.describe FrontendAPI::EventsController do
describe 'GET #index' do
let(:url) { 'http://subdomain.example.com' }
let(:bad_url) { 'http://foo.example.com' }
context 'wrong subdomain' do
it 'responds with 404' do
get "#{bad_url}/route"
expect(response).to have_http_status(:not_found)
end
end
end
end
There is a similar question and answer here testing routes with subdomain constraints using rspec
I had devise generate controllers for users with the console command rails generate devise:controllers users, and when I try to run a simple test for registrations_controller.rb my console outputs the error:
RuntimeError: #controller is nil: make sure you set it in your test's
setup method.
I am new to devise, but everything has seemed pretty straightforward so I don't really see why this isn't working.
This is app/controllers/users/registrations_controller.rb :
class RegistrationsController < Devise::RegistrationsController
# GET /resource/sign_up
def new
super
#user = User.new
end
end
This is config/routes.rb :
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: 'users/registrations'}
devise_scope :users do
root 'users/registrations#new'
get "sign_up", to: "users/registrations#new"
end
end
And this is test/controllers/registrations_controller_test.rb
require 'test_helper'
class RegistrationsControllerTest < ActionController::TestCase
include Devise::TestHelpers
def setup
#user = users(:user1)
end
test "should get new" do
get :new
assert_response :success
end
end
Any help you can provide is appreciated very much!
Per the Devise docs: "If you are testing Devise internal controllers or a controller that inherits from Devise's, you need to tell Devise which mapping should be used before a request." https://github.com/plataformatec/devise#test-helpers
class RegistrationsControllerTest < ActionController::TestCase
include Devise::TestHelpers
def setup
request.env['devise.mapping'] = Devise.mappings[:user]
#user = users(:user1)
end
test "should get new" do
get :new
assert_response :success
end
end
You may also need to prefix your test class like so:
class Users::RegistrationsControllerTest < ActionController::TestCase
...
end
I want to test my namespaced controllers but when I raise controller nothing raised and test is passing. I get no routes error. They all work fine. But it must raise error. Actually it must call index action but it does not. What is the cause?
dashboard_controller_spec.rb
require 'spec_helper'
describe Admin::DashboardController do
it "gets index" do
get :index
end
end
routes.rb
namespace :admin do
match 'dashboard' => 'dashboard#index', :as => :dashboard
end
dashboard_controller.rb
class Admin::DashboardController < Admin::ApplicationController
def index
raise "asd"
end
end
Hi you can write the route path as follow so get index action
describe :route do
subject { {get: "/Admin/dashboardes"} }
it { should route_to(controller: "Admin/dashboardes", action: "index") }
end
like example :
describe "#index" do
describe :route do
subject { {get: "/administration/users"} }
it { should route_to(controller: "administration/users", action: "index") }
end
end