سؤال

هل من الممكن اختبار استخدام تخطيط معين باستخدام RSpec مع Rails، على سبيل المثال، أرغب في استخدام أداة مطابقة تقوم بما يلي:

response.should use_layout('my_layout_name')

لقد وجدت أداة مطابقة use_layout عند البحث في Google ولكنها لا تعمل لأنه لا يبدو أن الاستجابة أو وحدة التحكم تحتوي على خاصية تخطيط كانت أداة المطابقة تبحث عنها.

هل كانت مفيدة؟

المحلول

لقد وجدت مثالا على كيف تكتب أ 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")

نصائح أخرى

نشر ديفيد تشيليمسكي إجابة جيدة على منتدى روبي:

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.
لقد قمت للتو بإضافة هذا الملف في دليل المواصفات/الدعم.الرابط هو: https://Gist.github.com/971342

# spec/support/matchers/render_layout.rb

ActionView :: base.class_eval do ما لم يكن exical_methods.include؟ ('_ render_layout_with_tracking') def _render_layout_with_tracking (التخطيط ، والسكان ، & block) controller.instance_varability_set (: _ render_layout ، layout) Ain: _render_layout ،: نهاية تتبع نهاية

# يمكنك استخدام هذا المطابقة في أي مكان يمكنك الوصول إلى مثيل وحدة التحكم ، كما هو الحال في مواصفات وحدة التحكم أو التكامل.# # == مثال الاستخدام # # لا يتوقع عدم تقديم تخطيط:# controller.sould_not render_layout # تتوقع أن يتم تقديم أي تخطيط:# controller.sould Render_layout # تتوقع تطبيق APP/Layouts/Application.html.erb:# controller.seld Render_layout ('application')# controller.seld_not render_layout ('application')# controller.should_not render_layout ('mobile/application') rspec :: matchers.define: render_layout do |*args | متوقع = args.first Match do | c | الفعلي = get_layout (c) إذا توقع. nil؟!actual.nil؟# الفعلي يجب أن يكون صفراً حتى ينجح الاختبار.الاستخدام:يجب أن_not redrend_layout elsif الفعلية == متوقعة

فشل _message_for_should do | c | الفعلي = get_layout (c) إذا كان actal.nil؟&& المتوقع.لا شيء؟"من المتوقع أن يتم تقديم تخطيط ولكن لم يكن" elsif فعليًا. nil؟"تخطيط متوقع #{متوقع.

فشل _message_for_should_not do | c | الفعلي = get_layout (c) إذا توقع. nil؟"متوقع عدم وجود تخطيط ولكن #{actual.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

يحرر:يوفر musta-matchers هذه الطريقة.ينبغي::Matchers::ActionController::RenderWithLayoutMatcher

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top