functional test to confirm custom route with devise - ruby-on-rails

I have a custom route for devise:
devise_scope :user do
get '/login' => "devise/sessions#new", :as => :new_user_session
get '/logout' => 'devise/sessions#destroy',
...
I want to make sure that when the request /login is called, that it gets correctly routed to devise and that the response is successful.
How do you test for custom routing and a successful request?

If you're using the built-in TestUnit to test, check out the Rails Guide on testing controllers.
If you're using Rspec, check out the Rspec Github Page for information on testing controllers.

It depends on you testing suite, personally I use RSpec + Capybara for my Rails projects.
If you don't have a testing suite yet I highly recommend this guide.
http://everydayrails.com/2012/03/12/testing-series-intro.html

In this particular instance, I'd say you want two tests. One for the routing and one for a successful request. Using rspec, this will look something like:
#spec/routing/devise_routing_spec.rb
require 'spec_helper'
describe "Devise Routes" do
it "should route the login correctly" do
{:get => "login"}.should route_to(controller: "devise/sessions", action: "new")
end
end
and
#spec/controllers/devise/session_controller_spec.rb
require 'spec_helper'
describe Devise::Sessions do
it "should be successful with a login request" do
get "new"
response.should be_success
end
end

Related

Rspec not finding routes that exists

I'm trying to write a controller test and Rspec isn't finding routes that I know exist and work fine on a development server.
In my routes I have a catch-all route that should redeirect to a generic controller if someone goes to a route that isn't predefined.
routes.rb
namespace :tools do
match '*unmatchedpath' => "generic#show", :via => :get
end
generic_controller.rb
def show
# do stuff
end
generic_controller_spec.rb
require 'spec_helper'
describe Tools::GenericController do
describe 'GET show' do
it 'does stuff' do
get :show
end
end
Here is the error I get from rspec when I run the test above
1) Tools::GenericController GET show does stuff
Failure/Error: get :show
ActionController::RoutingError:
No route matches {:controller=>"tools/generic", :action=>"show"}
All routes work as expected on my development server so I'm not sure why Rspec isn't finding the route.
Try:
get '*unmatchedpath' => 'tools/generic#show'

Testing Rails Controller: get and post strange behavior

I'm using RSpec (through the gem rspec-rails) for testing and developing
my application.
I've tried to "test" a controller and run up against a strange behavior of post and get methods (same for all the others of this kind).
In my route file:
controller :sessions do
post '/login', action: :login_create
get '/login', action: :login
get '/logout', action: :logout
end
At the beginning, I was thinking that post will simulate an http post
request at the specified url, so I've wrote in my spec:
describe "POST 'login'" do
it "returns http success" do
post 'login'
response.should be_success
response.should render_template 'sessions/login_create'
end
end
But this will call the login action, not the login_create, and then the last assert fail.
After a lot of googling and experiments, I've changed post 'login' with post :login_create and this actually works!
The strange thing is that also if I change post with get, it will continue to work! O_o
Isn't this strange? How this methods are intended to work and to be used?
In the Rails API I've not found anything else than the class: ActionController::TestCase::Behavior
What you're writing is a controller spec, not a request spec. In a controller spec, routes are not consulted at all because rspec invokes controller actions directly.
When you write post 'login', the login specifies the action name, not the URL path.
The correct way to test the login_create action would be to use post :login_create as you've discovered.

Unit testing a controller method that is called via a custom route

How do I unit test a controller method that is called via a custom route?
The relevant route is:
/auth/:provider/callback(.:format) {:controller=>"sessions", :action=>"create"}
On the spec for the SessionsController I can't just use get :create since that route doesn't exist. If I also use get /auth/facebook/callback/ it'll tell me that No route matches {:controller=>"sessions", :action=>"/auth/facebook/callback"}.
It also seems like I can't just use controller.create since #create accesses some keys from the request hash and it also redirects to another path, even if I set request.env['something'] in the spec file.
A functional test should test the function of each action
(given a set of parameters)
Crucially, you should keep your functional tests decoupled from your routes.
(else what's the point in the routing abstraction anyway)
In test::unit a functional test looks something like this
test "#{action_name} - does something" do
#{http_verb} :#{action_name}, :params => {:their => "values"}
assert_response :#{expected_response}
end
Note, we don't mention routing anywhere.
So a real example for your create
test "create - creates a session" do
get :create, :provider => "your provider"
assert_response :success
end
Rails will choke if it can't match a route to this request.
If this doesn't work I suggest you check two things
"get" is the correct http verb
there are no other required parameters in your route (I can see :provider is one)
If I'm doing anything wacky with routing,
I normally add a separate test.
test "create - routing" do
assert_recognizes({
:controller => "sessions",
:action => "create",
:provider => "yourProvider"
}, "/auth/yourProvider/callback")
end
As long as this matches up with your action test
all should be well.

Why doesn't this Rails Rspec Test Work?

I create all the routes of my program manually and so do with my rspec tests of course. Generally, my routes and tests work fine, but i have a problem with the test for my characters controller. The route is :
scope :path => '/characters', :controller => :characters do
get '/' => :show, :as => 'user_character'
end
The /characters works fine when tested with my browser. Everything seems fine. But, the test :
require 'spec_helper'
require 'devise/test_helpers'
describe CharactersController do
login_user
describe "when it GETS 'show'" do
it "should render the template and be successful" do
get :show
response.should render_template(:show)
response.should be_success
end
end
end
Fails with the error :
1) CharactersController when it GETS 'show' should render the template and be successful
Failure/Error: get :show
ActionController::RoutingError:
No route matches {:controller=>"characters", :action=>"show"}
# ./spec/controllers/characters_controller_spec.rb:9
All my controllers have similar tests that work fine. Why does this not work ?
IMPORTANT EDIT :
Just saw that if i turn Spork off, the test passes ! Why is this happening ? Does Spork need to be restarted every time a new test is added ?
You have to restart spork when changing routes.
Or put this in your spec_helper.rb:
Spork.each_run do
ApplicationName::Application.reload_routes!
end
See also "Speedy Test Iterations for Rails 3 with Spork and Guard"

Rails 3 and Rspec 2 namespaced controller problems

I;m trying to write a spec that tests a controller that is namespaced, let's call it Admin::FooController. My spec is called admin_foo_controller_spec.rb. In the spec, I'm trying to write a very basic spec to see if it can retrieve an action of a controller.
describe "GET 'index'" do
it "should be successful" do
get 'index'
response.should be_success
end
end
But instead I get an error:
Failure/Error: get 'index'
No route matches {:controller=>"admin/foo"}
For another action, I have basically the same test, and I get that the response is not successful. In the actual webapp, I can access these urls fine. One thing I should mention is that this isn't a RESTful resource (it makes no sense as one) so it's really just a group of related administrative actions, so in my routes.rb it's basically like
namespace :admin do
scope "foo" do
match "action1" => "foo#action1"
match "action2" => "foo#action2"
match "/index" => "foo#settings"
match "settings" => "foo#settings"
end
end
Any ideas what I'm doing wrong? It seems like namespacing is asking for trouble with rails, especially for a novice like me. Thanks!
In your route your have no index action in you Foo controller try to get 'settings'
describe "GET 'index'" do
it "should be successful" do
get 'settings'
response.should be_success
end
end
In a controller spec you need define the action of your controller not the real route. You try the routes in a integration test.

Resources