2008-09-20 9 views
26

Можно ли проверить использование данной компоновки с помощью RSpec с Rails, например, я хотел бы Сличитель, что делает следующее:Тестирование визуализации данного макета с RSpec & Rails

response.should use_layout('my_layout_name') 

I обнаружил совпадение use_layout, когда Googling, но он не работает, так как ни ответ, ни контроллер не имеют свойства макета, которое искали.

ответ

7

Я нашел пример how to write a use_layout matcher, который будет делать именно это. Вот код, в случае, когда связь идет прочь:

# in spec_helper.rb 

class UseLayout 
    def initialize(expected) 
    @expected = 'layouts/' + expected 
    end 
    def matches?(controller) 
    @actual = controller.layout 
    #@actual.equal?(@expected) 
    @actual == @expected 
    end 
    def failure_message 
    return "use_layout expected #{@expected.inspect}, got # 
{@actual.inspect}", @expected, @actual 
    end 
    def negeative_failure_message 
    return "use_layout expected #{@expected.inspect} not to equal # 
{@actual.inspect}", @expected, @actual 
    end 
end 


def use_layout(expected) 
    UseLayout.new(expected) 
end 

# in controller spec 
    response.should use_layout("application") 
+0

Это то же самое, что я нашел, и из моих тестов он, похоже, не работал, поскольку в ответе (или контроллере) нет атрибута макета из того, что я можно видеть. – DEfusion 2008-09-21 13:56:59

+0

А, кажется, есть способ макета, но он принимает некоторые аргументы. Я подумаю над тем, что такое решение. – Otto 2008-09-21 14:15:56

+0

On Rails 2.2.2 теперь и отлично работает – DEfusion 2009-02-21 19:55:35

16

Это работает для меня с края Rails и края RSpec на Rails:

response.layout.should == 'layouts/application' 

не должно быть трудно, чтобы превратить это в Сличитель подходящий для вы.

+0

Также работает для меня. – Otto 2009-01-31 00:14:41

+6

Это не работает в более новых версиях rspec. Вместо этого используйте `response.should render_template ('layouts/the_layout") ` – jpemberthy 2011-12-29 16:04:54

2

Вот обновленная версия помощника. Я обновил его, чтобы соответствовать последней версии RSpec. Я добавил соответствующие атрибуты только для чтения и удалю старый формат возврата.

# in spec_helper.rb 

class UseLayout 
    attr_reader :expected 
    attr_reader :actual 

    def initialize(expected) 
    @expected = 'layouts/' + expected 
    end 

    def matches?(controller) 
    if controller.is_a?(ActionController::Base) 
     @actual = 'layouts/' + controller.class.read_inheritable_attribute(:layout) 
    else 
     @actual = controller.layout 
    end 
    @actual ||= "layouts/application" 
    @actual == @expected 
    end 

    def description 
    "Determines if a controller uses a layout" 
    end 

    def failure_message 
    return "use_layout expected #{@expected.inspect}, got #{@actual.inspect}" 
    end 

def negeative_failure_message 
    return "use_layout expected #{@expected.inspect} not to equal #{@actual.inspect}" 
    end 
end 

def use_layout(expected) 
    UseLayout.new(expected) 
end 

Кроме сличитель теперь также работает с макетами, указанных на уровне класса контроллера и может быть использован следующим образом:

class PostsController < ApplicationController 
    layout "posts" 
end 

И в спецификации контроллера вы можете просто использовать:

it { should use_layout("posts") } 
1

controller.active_layout.name работает для меня.

0

Вот версия кода dmcnally, которая не позволяет передавать аргументы, делая работу «should use_layout» и «should_not use_layout» (утверждать, что контроллер использует любой макет, или нет макета соответственно), из которых я бы ожидать только второй, чтобы быть полезным, как вы должны быть более конкретными, если он использует макет):

class UseLayout 
    def initialize(expected = nil) 
    if expected.nil? 
     @expected = nil 
    else 
     @expected = 'layouts/' + expected 
    end 
    end 
    def matches?(controller) 
    @actual = controller.layout 
    #@actual.equal?(@expected) 
    if @expected.nil? 
     @actual 
    else 
     @actual == @expected 
    end 
    end 
    def failure_message 
    if @expected.nil? 
     return 'use_layout expected a layout to be used, but none was', 'any', @actual 
    else 
     return "use_layout expected #{@expected.inspect}, got #{@actual.inspect}", @expected, @actual 
    end 
    end 
    def negative_failure_message 
    if @expected.nil? 
     return "use_layout expected no layout to be used, but #{@actual.inspect} found", 'any', @actual 
    else 
     return "use_layout expected #{@expected.inspect} not to equal #{@actual.inspect}", @expected, @actual 
    end 
    end 
end 


def use_layout(expected = nil) 
    UseLayout.new(expected) 
end 
56

Дэвид Chelimsky разместил хороший ответ над на Ruby Forum:

response.should render_template("layouts/some_layout") 
+0

Это правильный ответ для Rspec 2. – Raphomet 2010-11-22 02:14:43

2

Вот решение, которое я закончил с этим. Его для rpsec 2 и rails 3.
Я просто добавил этот файл в каталог spec/support. Ссылка: https://gist.github.com/971342

# spec/support/matchers/render_layout.rb

ActionView::Base.class_eval do unless instance_methods.include?('_render_layout_with_tracking') def _render_layout_with_tracking(layout, locals, &block) controller.instance_variable_set(:@_rendered_layout, layout) _render_layout_without_tracking(layout, locals, &block) end alias_method_chain :_render_layout, :tracking end end

# You can use this matcher anywhere that you have access to the controller instance, # like in controller or integration specs. # # == Example Usage # # Expects no layout to be rendered: # controller.should_not render_layout # Expects any layout to be rendered: # controller.should render_layout # Expects app/views/layouts/application.html.erb to be rendered: # controller.should render_layout('application') # Expects app/views/layouts/application.html.erb not to be rendered: # controller.should_not render_layout('application') # Expects app/views/layouts/mobile/application.html.erb to be rendered: # controller.should_not render_layout('mobile/application') RSpec::Matchers.define :render_layout do |*args| expected = args.first match do |c| actual = get_layout(c) if expected.nil? !actual.nil? # actual must be nil for the test to pass. Usage: should_not render_layout elsif actual actual == expected.to_s else false end end

failure_message_for_should do |c| actual = get_layout(c) if actual.nil? && expected.nil? "expected a layout to be rendered but none was" elsif actual.nil? "expected layout #{expected.inspect} but no layout was rendered" else "expected layout #{expected.inspect} but #{actual.inspect} was rendered" end end

failure_message_for_should_not do |c| actual = get_layout(c) if expected.nil? "expected no layout but #{actual.inspect} was rendered" else "expected #{expected.inspect} not to be rendered but it was" end end

def get_layout(controller) if template = controller.instance_variable_get(:@_rendered_layout) template.virtual_path.sub(/layouts\//, '') end end end

4

Я должен был написать следующее, чтобы сделать эту работу:

response.should render_template("layouts/some_folder/some_layout", "template-name") 
1

response.should render_template("layouts/some_folder/some_layout") response.should render_template("template-name")

14

Там уже совершенно функциональные согласовани для этого:

response.should render_template(:layout => 'fooo') 

(Rspec 2.6. 4)

0

Соискатели предназначены для этого сценария.(Documentation) Это похоже на работу:

 expect(response).to render_with_layout('my_layout') 

производит соответствующие сообщения об ошибках, как:

Ожидаемое для визуализации с макетом «calendar_layout», но оказывается с «приложения», «приложение»

Испытано с rails 4.2, rspec 3.3 и shoulda-matchers 2.8.0

Редактирование: эталонный метод позволяет использовать этот метод. Shoulda :: Matchers :: ActionController :: RenderWithLayoutMatcher