I've overridden Refinery's session controller and not even modified it yet, as I'm trying to write some specs for it.
The controller lives in app/controllers/refinery/sessions_controller:
module Refinery
class SessionsController < Devise::SessionsController
....
def create
super
rescue ::BCrypt::Errors::InvalidSalt, ::BCrypt::Errors::InvalidHash
flash[:error] = t('password_encryption', :scope => 'refinery.users.forgot')
redirect_to refinery.new_refinery_user_password_path
end
.....
I then am trying to write a spec against this in spec/controllers/refinery/sessions_controller_spec.rb:
require 'spec_helper'
describe Refinery::SessionsController do
it "should post ok" do
post :create
response.should be_success
end
end
However this is giving me an error
No route matches {:action=>"create", :controller=>"refinery/sessions"}
This confuses me as when I run rake routes, I get the following line:
refinery_user_session POST /refinery/users/login(.:format) refinery/sessions#create
Could anyone help?
Rails 3.2.8, refinery 2.0.8
Related
I am new to Rails and Rspec and trying to write spec to test one non RESTful controller action.
Spec code:
require 'rails_helper'
RSpec.describe ReportsController, type: :controller do
describe "GET /full_members" do
context "when current account doesn't have contacts" do
let!(:current_account) { create(:account) }
it "hit full_members action" do
expect(get: '/reports/full_members').to be_routable
expect(:get => "/reports/full_members").to route_to(
controller: "reports",
action: "full_members")
get :full_members
end
end
end
end
Controller code:
class ReportsController < ApplicationController
def full_members
require "pry"
binding.pry
set_select_options_full_members
#members = #current_account.contacts
end
...
I was expecting to execute spec and stop at the breaking point pry. But the actual result is spec passed and pry didn't work.
Finished in 0.17359 seconds (files took 1.16 seconds to load)
1 example, 0 failures
From rails routes I can see the route exists(the spec first two assertions also prove that)
~ยป rails routes | ag full_members
>> full_members_reports GET /reports/full_members(.:format)
My routes.rb
resources :reports, only: [:index] do
collection do
get 'full_members'
end
end
Can not figure out why the pry didn't work in controller action. Can anyone help with that? Thanks
I have 2 versions of my API(1&2) the controller of api version 2 inherits from the controller of api version 1. The problem is, specs for version 1 are running fine, but when i run specs in version 2, it tells me
ActionController::UrlGenerationError: No route matches {:action=>"create", :controller=>"api/mobile/v2/samples"}
#version 1
class Api::Mobile::V1::SamplesController < ApplicationController
def create
#dummy
end
end
#version 2
require "meta_data"
class Api::Mobile::V2::SamplesController < Api::Mobile::V1::SamplesController
include MetaData
end
#spec for version 1
require 'rails_helper'
RSpec.describe Api::Mobile::V1::SamplesController, type: :controller do
describe "POST #create" do
it "performs a post" do
post :create
end
end
end
#spec for version 2
require 'rails_helper'
RSpec.describe Api::Mobile::V2::SamplesController, type: :controller do
describe "POST #create" do
it "performs a post" do
post :create
end
end
end
RSpec is looking for SamplesController (plural). Make sure you are specifying your routes using singular resource if that's what you have. Otherwise, specify plural form of sample as sample in an initializer.
I would just go with the flow and user plural form. But, obviously with the public API that's a real headache.
I am learning Rails and very new to testing but so far I've managed to build something with minimal errors. However, the issue I am running into is that my tests are complaining for methods that cannot be found and no route matching.
To my understanding tests should be run frequently based Hartl's - Railstutorial 3.3. Many StackO threads and online articles seem to pertain to utilizing test suites I don't use like RSpec, etc...so the test configurations are confusing. My testing suite is set up similiar to Hartl's - Railstutorial 3.3 and below are the gems loaded for testing.
gem 'better_errors', '~> 2.1.1'
gem 'binding_of_caller'
gem 'minitest-reporters', '1.0.5'
gem 'mini_backtrace', '0.1.3'
gem 'guard-minitest', '2.3.1'
gem 'ruby-prof'
NoMethodError: undefined method
Error: (_I have two error similar errors to below_)
ServicesControllerTest#test_should_get_index:
NoMethodError: undefined method 'services' for nil:NilClass
app/controllers/services_controller.rb:6:in 'index'
test/controllers/services_controller_test.rb:9:in 'block in <class:ServicesControllerTest>"
Services Controller
def index
#services = current_tech.services
end
services_controller_test.rb
require 'test_helper'
class ServicesControllerTest < ActionController::TestCase
setup do
#service = services(:one)
end
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:services)
end
end
I believe the reason I am receiving this error is because of Devise.
If I were to setup the following index action below, the test will pass.
def index
#services = Tech.first.services
end
How do I correct this so that this test passes?
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"tech"}
Error:
CarsControllerTest#test_should_get_show:
ActionController::UrlGenerationError: No route matches {:action=>"show", :controller=>"cars"}
test/controllers/cars_controller_test.rb:5:in `block in <class:CarsControllerTest>
Rake routes pertaining to cars
tech_cars POST - /techs/:tech_id/cars(.:format) - cars#create
car GET - /cars/:id(.:format) - cars#show
Routes
Rails.application.routes.draw do
devise_for :customers, controllers: { sessions: 'customers/sessions' }
devise_for :techs, controllers: { sessions: 'techs/sessions' }
resources :techs, :only => [:index, :show], shallow: true do
resources :cars, only: [:show, :create]
end
resources :services, :garages
root "home#index"
end
cars_controller.rb
class CarsController < ApplicationController
before_action :set_car
def show
#garage = Garage.find(params[:id])
#tech = #tech.service.car.id
end
def create
#garage = Garage.create(tech_first_name: #car.service.tech.first_name,
customer_id: current_customer.id,
customer_street_address: current_customer.street_address,
customer_city: current_customer.city,
customer_state: current_customer.state,
customer_zip_code: current_customer.zip_cod)
if #garage.save
redirect_to techs_path, notice: "Working"
else
redirect_to techs_path, notice: "Uh oh, flat tire"
end
end
private
def set_car
#car = Car.find(params[:id])
end
def car_params
params.permit(:service_name, :garage_photo)
end
end
cars_controller_test.rb
require 'test_helper'
class CarControllerTest < ActionController::TestCase
test "should get show" do
get :show
assert_response :success
end
end
cars.html.erb (only links on page)
<%= button_to 'View Garage', tech_cars_path(tech_id: #car.service.tech.id, id: #car) %>
<%= link_to 'Back to tech', tech_path(#car.service.tech.id) %>
As you may gather, I am building a Garage not a Car object within the Cars controller. Would this be a problem for tests? My application functions fine as is. On a side note, I am also having difficulty trying to associate car_params strong params for instance variables but that's another StackO post.
*test/test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require "minitest/reporters"
Minitest::Reporters.use!
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Add more helper methods to be used by all tests here...
end
class ActionController::TestCase
include Devise::TestHelpers
end
Is there something I am missing or haven't configured correctly?
Please know my application appears to be working fine, it's just I would like to suppress these tests errors.
Please advise on how to get these test errors to pass.
Thanks
First issue: Your feeling is correct. Devise comes with Devise::TestHelpers which you've mixed into ActionController::TestCase in your test helper file. One of the methods it provides is sign_in which lets you spoof a logged in user as part of your test. Assuming you've got a model called Tech and you're following standard Rails conventions, you'll need to add something like:
sign_in techs(:some_tech)
to either your setup block or directly into your test body before the call to get :index. That will ensure that current_tech returns something non-nil and remove the immediate NoMethodError.
Second issue: Your :show action expects to receive the ID of a known Car as part of the URL. Replace your current invocation of the controller with:
require 'test_helper'
class CarControllerTest < ActionController::TestCase
setup do
#car = cars(:some_car)
end
test "should get show" do
get :show, id: #car.id
assert_response :success
end
end
I'm writing tests with rspec for my application controller in my rails app (written in Rails 4) and I'm running into a problem where it doesn't recognize the route for the HTTP request I'm sending. I know there's a way to do this using MyApp::Application.routes but I'm not able to get it working.
#application_controller_spec.rb
require 'spec_helper'
class TestController < ApplicationController
def index; end
end
describe TestController do
before(:each) do
#first_user = FactoryGirl.create(:user)
# this is to ensure that all before_filters are run
controller.stub(:first_time_user)
controller.stub(:current_user)
end
describe 'first_time_user' do
before(:each) do
controller.unstub(:first_time_user)
end
context 'is in db' do
before(:each) do
#user = FactoryGirl.create(:user)
controller.stub(:current_user).and_return(#user)
end
it 'should not redirect' do
get :index
response.should_not be_redirect
end
end
context 'is not in db' do
context 'session[:cas_user] does not exist' do
it 'should return nil' do
get :index
expect(assigns(:current_user)).to eq(nil)
end
end
it "should redirect_to new_user_path" do
controller.stub(:current_user, redirect: true).and_return(nil)
get :index
response.should be_redirect
end
end
end
The error I'm getting right now is
No route matches {:action=>"index", :controller=>"test"}
I would add the test#index route to config/routes.rb, but it doesn't recognize the Test Controller, so I want to do something like
MyApp::Application.routes.append do
controller :test do
get 'test/index' => :index
end
end
but I'm not sure where to add this or if this even works in rspec. Any help would be great!
If you are trying to test your ApplicationController, see this RSpec documentation about it. You will need to define methods like index inside the test, but it works well.
I am currently trying to test a custom Devise session controller with rspec. My controller looks like this:
class SessionsController < Devise::SessionsController
def create
#valid email?
if !(params[:email] =~ /^[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/)
set_flash_message :notice, "Please enter a valid e-mail address!"
end
super
end
end
My RSpec Controller Test is this:
require 'spec_helper'
require 'devise/test_helpers'
describe SessionsController do
it "should put a warning on invalid mail address login attempt" do
post :create, :user => {:email => 'invalidEmailAddress'}
response.should contain "Please enter a valid e-mail address!"
end
it "should put no warning on valid mail address login attempt" do
pending
end
end
If I execute the RSpec Test it fails with the following line:
Failure/Error: post :new, :user => {:email => 'invalidEmailAddress'}
AbstractController::ActionNotFound
# ./spec/controllers/sessions_controller_spec.rb:7
Tips from the plataformatec Devise Wiki as well as this post did not solve this issue. Thanks for your help.
Addition
I investigated further. I was actually able to "remove" the error with the following addition to the controller spec:
before(:each) do
request.env['devise.mapping'] = Devise.mappings[:user]
end
But now a new error appears:
Failure/Error: post :create #currently fails with multiple render warning
Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
Even with the create method left out in the inheriting controller the error appears. The error does not appear on get :new for example. It seems to be post :create only.
I am out of ideas? Any help?
Thanks!
I finally fixed my problem by doing including the devise test helpers, calling the method setup_controller_for_warden in my test AND doing request.env["devise.mapping"] = Devise.mappings[:user]. Like so:
require 'test_helper'
class SessionsControllerTest < ActionController::TestCase
include Devise::TestHelpers
test "should reject invalid captcha" do
setup_controller_for_warden
request.env["devise.mapping"] = Devise.mappings[:user]
get :new
assert_response :success
end
end
Not sure about your double render problem though, are you sure your supposed to call post :create then render? i'm not sure how rspec is supposed to work.