Undefined method `get' for #<RSpec::Core::ExampleGroup::Nested_1 displayed in Rspec Controllers - ruby

After running the following code from Rspec - Controllers, I get an error from the get method
it "assigns #MyItems" do
my_item = mock(:mypay_items)
my_item = mock( MyItem)
MyItem.should_receive(:all).and_return(my)
get 'index'
assigns[:my_items].should eql(my_items)
response.should be_success
end
It results in an error:
undefined method `get' for #<RSpec::Core::ExampleGroup::Nested_1:0x34b6ae0>

It would seem that you're not properly declaring your spec as a controller spec, which results in the HTTP request methods (get, post, etc.) not being available. Make sure that at the top of your spec, you have something like:
describe PostsController do
...
end
Replace PostsController with the name of your controller. If that doesn't work, add :type => :controller:
describe PostsController, :type => :controller do
...
end
See also this answer: undefined method `get' for #<RSpec::Core::ExampleGroup::Nested_1:0x00000106db51f8>

If at all you are using 'spec/features', you may need to add the following to your 'spec_helper.rb'
config.include RSpec::Rails::RequestExampleGroup, type: :feature

I had the same problem and the solution that worked for me was to add require 'rspec/rails' to my spec_helper file. All my controllers were setup correctly and adding the :type => controller didn't help.

Related

Could not find devise mapping for path

I have the following routes defined in my routes.rb
devise_for :users, controllers: { registrations: "network/registrations",sessions: 'network/sessions', passwords: 'network/passwords' }
devise_scope :user do
get "registrations/show" => "network/registrations", as: :show_user_profile
end
and when i do rake routes i also see
network_show_user_profile GET /network/registrations/show(.:format) network/registrations#show
But when i try to access the path /network/registrations/show
i get the below exception
Could not find devise mapping for path "/network/registrations/show".
This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example:
devise_scope :user do
get "/some/route" => "some_devise_controller"
end
2) You are testing a Devise controller bypassing the router.
If so, you can explicitly tell Devise which mapping to use:
#request.env["devise.mapping"] = Devise.mappings[:user]
I tried to modify the routes.rb and added
devise_scope :user do
get 'user_profile' => 'registrations#search', :as => 'user_profile'
end
and when i access user_profile path, i get the error
The action 'show' could not be found for Network::RegistrationsController
but when i add the action show to the controller I again get the same exception message
Could not find devise mapping for path "/network/registrations/show".
This may happen for two reasons:
1) You forgot to wrap your route inside the scope block. For example:
devise_scope :user do
get "/some/route" => "some_devise_controller"
end
2) You are testing a Devise controller bypassing the router.
If so, you can explicitly tell Devise which mapping to use:
#request.env["devise.mapping"] = Devise.mappings[:user]
any help as to what i am doing wrong would be appreciated. Thanks.
I tried adding same routes that you did
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: "network/registrations",sessions: 'network/sessions', passwords: 'network/passwords' }
devise_scope :user do
get "registrations/show" => "network/registrations", as: :show_user_profile
end
end
But instead of
network_show_user_profile GET /network/registrations/show(.:format)
I got show_user_profile GET /registrations/show(.:format) registrations#show
So I replaced this routes file with below
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: "network/registrations",sessions: 'network/sessions', passwords: 'network/passwords' }
devise_scope :user do
get "/network/registrations/show" => "network/registrations#show", as: :show_user_profile
end
end
I also created an action show in network/registrations_controller.rb and
everything works perfectly for me.
Hope this helps.

How to write specific custom routes for rails + devise?

I am trying to write a custom route that will point to a custom controller action in devise.
I have the setup below right now.
# custom controller
class Registrations::RegistrationsController < Devise::RegistrationsController
layout 'settings'
# GET /resource/edit
def edit
super
end
end
# routing setup
Rails.application.routes.draw do
devise_for :users, controllers: { registrations: "registrations/registrations" },
path_names: { edit: 'profile' }
end
This allows me to have a custom URL localhost:4000/users/profile with no problems.
My question is how can I customize this further to be
localhost:4000/profile
localhost:4000/settings/profile
Note I know that I can set path: '' or path: 'settings', but that will affect all routes within users.
Is there a way that I could have
localhost:4000/settings/profile and localhost:4000/login at the same time using devise_for?
I am not sure how to control these affects separately.
As we can see here, we can use Rails scopes and specify a controller for 'registration', for example. Something like this:
scope :settings do
devise_scope :user do
get '/profile' => 'devise/registrations#edit'
end
end

RSpec controller lookup

I'm trying to define a RSpec test for a controller named FindWithSameDirectorController.
I got a ActionController::RoutingError. No route matches {:id => 1, :controller => 'find_with_same_director', : action => 'show'}.
The controller name doesn't match the controller that i define.
How does rspec determines this name ? Is it possible to change it ?
Thx
Bertrand
Your spec propably looks like this:
describe FindWithSameDirectorController do
it { should route(:get, '/find_with_same_director/1').to action: 'show', id: 1 }
end
but in your config/routes.rb you have either missing a line like
resources :find_with_same_director
(or this resource is overwritten by another route specification).

testing private before filter that relies on request body in rspec

I have the following controller:
class ApiController < ApplicationController
before_filter :authenticate_user_from_token!
private
def authenticate_user_from_token!
#json = JSON.parse(request.body.read)
--auth logic goes here extracting user credentials goes here--
request.body.rewind
if auth_valid
authenticate
else
render nothing: true, status: :unauthorized
end
end
end
Testing this method has proven to be surprisingly difficult. I have tried the following approaches:
1) Sending the private method directly:
#controller.send(authenticate_user_from_token!)
The flaw here, is that I am unsure how to mock out request.body to contain valid/invalid credentials. I have tried the following:
before do
class Hash
def body
self['body']
end
end
#request = {}
#request['body'] =StringIO.new({auth_goes_here}.to_json)
end
However, in the method, request still gets overriden with a brand new ActionController::TestRequest.
2) Posting directly:
before do
post :authenticate_user_from_token!, my_preconstructed_credentials, format: :json
end
which results in:
*** AbstractController::ActionNotFound Exception: The action 'authenticate_user_from_token!' could not be found for ApiController
3) Defining an exposed method at runtime:
before do
#controller.class_eval <<-RUBY_EVAL
public
def update
end
RUBY_EVAL
end
followed by post :update, which still results in *** NoMethodError Exception: undefined methodfoobar' for #`
My question is: how can I test a private before filter on a controller that depends on request.body? I realize I could mock out request and body in my third approach, but I would still require it to respond to read/rewind. How is this kind of method usually tested?
In the end, the following worked:
before do
class ::TestApiController < ApiController
def hello
render nothing: true
end
end
Rails.application.routes.draw do
match 'hello', to: 'test_api#hello'
end
#controller = TestApiController.new
#request.env['RAW_POST_DATA'] = my_awesome_json
post :hello
end

New routes overriding previously instantiated

I must be missing something from Rack's non-existant docs :) I'm trying to add additional webservice routes to ruhoh, and can get them to work at localhost:9292/test, but the new Rack::Builder object seems to override the last, as I can no longer access the default blog at localhost:9292/. I've tried different ways of defining the new routes without declaring Rack::Builder.new, but can't get anything to work.
What is the best way to add additional routes using this interface?
require 'rack'
require 'ruhoh'
run Ruhoh::Program.preview
# Additional routes
builder = Rack::Builder.new do
use Rack::CommonLogger
map '/test' do
run Proc.new {|env| [200, {"Content-Type" => "text/html"}, StringIO.new("infinity 0.1")] }
end
end
run builder
In the way you use it, run Ruhoh::Program.preview will never serve requests.
You should put it into builder:
builder = Rack::Builder.new do
use Rack::CommonLogger
map '/' do
run Ruhoh::Program.preview
end
map '/test' do
run Proc.new {|env| [200, {"Content-Type" => "text/html"}, StringIO.new("infinity 0.1")] }
end
end
run builder

Resources