Тестирование рендеринга заданного макета с помощью RSpec & Rails - PullRequest
27 голосов
/ 21 сентября 2008

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

response.should use_layout('my_layout_name')

Я нашел matcher use_layout при поиске в Google, но он не работает, поскольку ни у ответа, ни у контроллера нет свойства макета, которое искал matcher.

Ответы [ 11 ]

56 голосов
/ 28 сентября 2010

Дэвид Челимски опубликовал хороший ответ на форуме Ruby :

response.should render_template("layouts/some_layout")
16 голосов
/ 27 сентября 2008

Это работает для меня с пограничными Rails и пограничными RSpec on Rails:

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

Не должно быть трудно превратить это в подходящее для вас совпадение.

15 голосов
/ 28 мая 2012

Для этого уже есть идеально функциональный подход:

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

(Rspec 2.6.4)

7 голосов
/ 21 сентября 2008

Я нашел пример , как написать 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")
5 голосов
/ 09 января 2012

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

response.should render_template("layouts/some_folder/some_layout", "template-name")
2 голосов
/ 16 мая 2011

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

# spec/support/matchers/render_layout.rb</p>

<p>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</p>

<p># 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</p>

<p>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</p>

<p>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</p>

<p>def get_layout(controller)
    if template = controller.instance_variable_get(:@_rendered_layout)
      template.virtual_path.sub(/layouts\//, '')
    end
  end
end
2 голосов
/ 22 августа 2009

Вот обновленная версия matcher. Я обновил его, чтобы соответствовать последней версии 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 голос
/ 18 мая 2012

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

1 голос
/ 24 августа 2009

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

0 голосов
/ 31 июля 2015

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

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

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

Ожидается рендеринг с макетом calendar_layout, но рендеринг с применением, application, 1011 ** 1012 Протестировано с rails 4.2, rspec 3.3 и shoulda-matchers 2.8.0

Редактировать: musta-matchers предоставляет этот метод. Shoulda :: Matchers :: ActionController :: RenderWithLayoutMatcher

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...