문제

Rails와 함께 RSpec을 사용하여 주어진 레이아웃의 사용을 테스트하는 것이 가능합니까? 예를 들어 다음을 수행하는 매처를 원합니다:

response.should use_layout('my_layout_name')

인터넷 검색에서 use_layout 매처를 찾았지만 응답이나 컨트롤러 모두 매처가 찾고 있던 레이아웃 속성이 없는 것 같아서 작동하지 않습니다.

도움이 되었습니까?

해결책

나는 예를 찾았다. 어떻게 쓰는지 use_layout 매처 그게 바로 그 일이 될 것입니다.링크가 사라지는 경우를 대비한 코드는 다음과 같습니다.

# 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")

다른 팁

David Chelimsky가 좋은 답변을 게시했습니다. 루비 포럼:

response.should render_template("layouts/some_layout")

이것은 Edge Rails 및 Edge RSpec on Rails에서 작동합니다.

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

이것을 당신에게 적합한 matcher로 바꾸는 것은 어렵지 않을 것입니다.

이에 대해 완벽하게 기능하는 일치자가 이미 있습니다.

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

(R스펙 2.6.4)

이 작업을 수행하려면 다음을 작성해야 했습니다.

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

다음은 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") }

내가 결국 해결 한 해결책은 다음과 같습니다.rpsec 2 및 레일 3용입니다.
방금 spec/support 디렉토리에 이 파일을 추가했습니다.링크는 다음과 같습니다: https://gist.github.com/971342

# spec/support/matchers/render_layout.rb

actionView :: base.class_eval instance_methods.include? ethod_chain : _render_layout, : 추적 끝 끝

# 컨트롤러 또는 통합 사양과 같은 컨트롤러 인스턴스에 액세스 할 수있는이 매치기를 사용할 수 있습니다.# # == 예제 사용 # # 레이아웃이 렌더링되지 않을 것으로 예상합니다.# controller.should_not render_layout # 모든 레이아웃이 렌더링 될 것으로 예상합니다.# controller.sh render_layout # app/views/layouts/application.html.erb가 렌더링 될 것으로 기대합니다.# controller.sh render_layout ( 'Application') # 앱/뷰/레이아웃/application.html.erb를 기대합니다.# controller.should_not render_layout ( '응용 프로그램') # 앱/보기/레이아웃/mobile/application.html.erb가 렌더링 될 것으로 기대합니다.# controller.should_not render_layout ( 'mobile/application') rspec :: matchers.define : render_layout do |*args | 예상 = args.first match do | c | 실제 = get_layout (c) 예상되는 경우?!실제.nil?# 테스트를 통과하려면 실제값이 nil이어야 합니다.용법:DUTE_ render_layout elsif 실제 실제 == excling.to_s else false end end

실패 _message_for_should do | c | 실제 = get_layout (c) 실제 .nil 인 경우?&& 예상됨.nil?"레이아웃이 렌더링 될 것으로 예상되었지만"Elsif actual.nil?"예상 레이아웃 #{exposs.inspect}이지만"else "예상 레이아웃 #{expect.Inspect}이 렌더링되지 않았지만 #{acture.inspect}가 렌더링되었습니다.

실패 _message_for_should_not do | c | 실제 = get_layout (c) 예상되는 경우?"예상 레이아웃은 없지만 #{actual.inspect}가"else "exposs #{exposs.inspect} 렌더링되지 않았지만"종료 끝이었습니다.

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

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

controller.active_layout.name 나를 위해 일합니다.

다음은 인수 전달을 허용하지 않는 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

마땅히 매처스 이 시나리오에 대한 일치자를 제공합니다.(선적 서류 비치) 이것은 작동하는 것 같습니다.

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

다음과 같은 적절한 실패 메시지가 생성됩니다.

"calendar_layout" 레이아웃으로 렌더링할 것으로 예상되었지만 "application", "application"으로 렌더링되었습니다.

테스트됨 rails 4.2, rspec 3.3 그리고 shoulda-matchers 2.8.0

편집하다:shoulda-matchers는 이 방법을 제공합니다.Shoulda::Matchers::ActionController::RenderWithLayoutMatcher

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top