Совершенствование макроса RSpec для контроллеров - PullRequest
0 голосов
/ 19 октября 2010

Я пытаюсь создать простой макрос для приложения Rails, которое использует Devise для аутентификации.По сути, я хочу убедиться, что когда пользователь заходит на страницу, требующую аутентификации, он перенаправляется на страницу входа.Так что-то вроде этого:

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

Желаемые результаты здесь должны быть очевидны.Моя проблема, однако, в том, что я не могу придумать лучший способ сопоставить каждое действие соответствующему методу http (: get,: post и т. Д.)

Я начал с этого:

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

Что, конечно, только получает.Может кто-нибудь сказать мне, как я мог бы предоставить этот макрос для всех действий?Я предполагаю, что мне нужно как-то проверить правильность маршрутов действий для определенного метода, но я просто не совсем уверен.

Любая помощь очень ценится.

Ответы [ 3 ]

1 голос
/ 08 февраля 2011

Может быть, старый, но все еще может помочь.

Вот хороший и простой способ определения макросов в RSpec (даже для контроллеров).

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

Посмотрите, используя метод отсутствия, вы можете записать определенное поведение в записанные макросы, например, это спецификация контроллера скаффолда с определенной инструкцией-заглушкой:

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 голосов
/ 11 октября 2011

Этот Railscast покрывает именно то, что вы ищете: http://railscasts.com/episodes/157-rspec-matchers-macros

Похоже, вы можете просто вызвать метод get с желаемым действием в спецификации вашего контроллера, и он вызовет соответствующий метод вконтроллер.

Вот моя версия макроса:

# 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
0 голосов
/ 23 октября 2010

Я использую следующее, пока не придумаю что-нибудь более элегантное:

# 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

Кстати, мне еще нужно расширить его для работы с маршрутами, такими как:

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