2010-10-19 3 views
0

Je tente de générer une macro simple pour une application Rails qui utilise Devise pour l'authentification. Fondamentalement, je veux m'assurer que lorsqu'un utilisateur accède à une page nécessitant une authentification, il est redirigé vers la page de connexion. Donc, quelque chose comme ceci:Perfection d'une macro RSpec pour les contrôleurs

it_requires_authentication_for :index, :new, :create, :update 

Les résultats souhaités ici devraient être évidents. Mon problème est cependant que je ne peux pas penser à la meilleure façon de cartographier chaque action à sa méthode appropriée http (: obtenez,: après etc ...)

J'ai commencé avec ceci:

def it_should_require_authentication_for(*actions) 
    actions.each do |action| 
    it "should require authentication for #{action}" do 
     get action.to_sym 
     response.should redirect_to(new_user_session_path) 
    end 
    end 
end 

Qui bien sûr ne fait que le get. Quelqu'un peut-il me dire comment je pourrais fournir cette macro pour toutes les actions? Je suppose que j'ai besoin de tester en quelque sorte si l'action route correctement pour une méthode particulière, mais je ne suis pas vraiment sûr.

Toute aide est grandement appréciée.

Répondre

0

J'utilise ce qui suit jusqu'à ce que je viens avec quelque chose de plus élégant:

# controller_macros.rb 
def it_should_recognize_and_generate_routes_for(controller, routes) 
    describe "routing" do 
    routes.each do |route| 
     action = route[:action].to_s 
     method = route[:method] || :get 
     url  = controller + (route[:url] || '') 
     params = route.reject {|k, v| [:action, :method, :url].include?(k) } 
     expected = { :controller => controller, :action => action }.merge(params) 

     it "should recognize and generate '#{action}'" do 
     { method => url }.should route_to(expected) 
     end 
    end 
    end 
end 

# posts_controller_spec.rb 
describe Forum::PostsController do 
    it_should_recognize_and_generate_routes_for('forum/posts', [ 
    { :action => :new, :url => '/new' }, 
    { :action => :create, :method => :post }, 
    { :action => :show, :url => '/1', :id => '1' }, 
    { :action => :index }, 
    { :action => :edit, :url => '/1/edit', :id => '1' }, 
    { :action => :update, :method => :put, :url => '/1', :id => '1' }, 
    { :action => :destroy, :method => :delete, :url => '/1', :id => '1' } 
    ]) 
end 

BTW je dois encore l'étendre à travailler avec les routes comme:

get 'login' => 'user_sessions#new' 
1

peut-être vieux, mais peut encore aider certains.

Voici une façon simple et facile de définir des macros dans RSpec (même pour les contrôleurs).

http://osmose.6spot.com.br/2011/02/better-macros-with-rspec/

Regardez, en utilisant la méthode que vous manque, ce sont en mesure d'enregistrer un comportement spécifique dans vos macros enregistrées, par exemple, ceci est une spécification de contrôleur d'échafaudage avec une instruction stub spécifique:

 
describe CustomersController do 

    before(:each) do 
    mock_filter(:require_user_owner) 
    end 

    # GET /customers 
    get :index do 
    default :stub => :off 

    before(:each) do 
     Customer.stub(:find_all_by_user_id) { [mock_customer] } 
    end 
    end 

    # GET /customers/6 
    get :show, :id => 6 

    # GET /customers/new 
    get :new 

    # GET /customers/6/edit 
    get :edit, :id => 6 

    # POST /customers 
    post :create 

    # PUT /customers/6 
    put :update, :id => 6 

    # DELETE /customers/6 
    delete :destroy, :id => 6 

end 
0

Cette Railscast couvre exactement ce que vous cherchez: http://railscasts.com/episodes/157-rspec-matchers-macros

Il semble que vous pouvez simplement appeler la méthode get avec l'action désirée dans votre spécification de contrôleur, et il appellera la méthode appropriée dans le contrôleur.

Voici ma version de la macro:

# Last argument is an optional hash of http arguments 
# which is useful when working with nested models 
# 
# ex it_should_require_login_for_actions(:index,:new,:create, {:parent_id=>1}) 
# 
def it_should_require_login_for_actions(*actions) 
    request_args = {:id => 1} 

    #If the last element of the actions list is a hash, then merge it 
    # with the existing request arguments 
    if actions[-1].is_a?(Hash) 
    request_args.merge!(actions.pop()) 
    end 

    actions.each do |action| 
    it "#{action} action should require login" do 
     get action, request_args 
     response.should redirect_to(login_url) 
    end 
    end 
end 
Questions connexes