RSpec と Rails を使用した特定のレイアウトのレンダリングのテスト

StackOverflow https://stackoverflow.com/questions/109284

  •  01-07-2019
  •  | 
  •  

質問

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'

これを自分に合ったマッチャーに変えるのは難しくないはずです。

これに関しては、完全に機能するマッチャーがすでに存在します。

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

(仕様 2.6.4)

これを機能させるには次のように記述する必要がありました。

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

これはマッチャーの更新バージョンです。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 と Rails 3 用です。
このファイルを spec/support ディレクトリに追加しました。リンクは次のとおりです。 https://gist.github.com/971342

# spec/support/matchers/render_layout.rb

ActionView :: base.class_eval instance_methods.include?( '_ render_layout_with_tracking')def _render_layout_with_tracking(layout、locals&&block)controller.instance_variable_set(:@_ rendered_layout、leaut、leaut) as_method_chain:_render_layout、:追跡エンドエンド

#コントローラーインスタンスにアクセスできるこのマッチャーは、コントローラーや統合仕様のように、どこでも使用できます。##==模範の使用##レイアウトがレンダリングされないと予想してください:#Controller.should_not render_layout#レイアウトがレンダリングされることを期待しています。#controller.show render_layout#アプリ/ビュー/レイアウト/application.html.erbがレンダリングされることを期待してください:#controller.show render_layout( 'application')#Controller.should_not render_layout( 'application')#controller.should_not render_layout( 'mobile/application')rspec :: matchers.define:render_layout do |*args |期待= args.first match do | c | everity = get_layout(c)sequient.nil?!actual.nil?# テストに合格するには、actual は nil でなければなりません。使用法:shuld_not render_layout elsif eracty eracted.to_s else false end end

fails_message_for_は| c |を行う必要がありますfartice = get_layout(c)farticy.nil?&& 期待されています。nil?「レイアウトがレンダリングされることを期待していましたが、誰もいませんでした。「予想されるレイアウト#{expection.inspect}がレイアウトは「else」のレンダリングされていません。

fails_message_for_should_not do | c | everity = get_layout(c)sequient.nil?「レイアウトは予想されませんが、#{実際の.inspect}が「else」とレンダリングされました。

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 」を機能させます(それぞれ、コントローラーが任意のレイアウトを使用しているか、またはレイアウトを使用していないことをアサートします。そのうちの 2 番目のみを期待します)レイアウトを使用している場合はより具体的にする必要があるため、便利です):

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