lib/remarkable/dsl/assertions.rb in remarkable-3.1.6 vs lib/remarkable/dsl/assertions.rb in remarkable-3.1.7
- old
+ new
@@ -1,121 +1,121 @@
module Remarkable
- module DSL
- # This module is responsable to create a basic matcher structure using a DSL.
- #
- # A matcher that checks if an element is included in an array can be done
- # just with:
- #
- # class IncludedMatcher < Remarkable::Base
- # arguments :value
- # assertion :is_included?
- #
- # protected
- # def is_included?
- # @subject.include?(@value)
- # end
- # end
- #
- # As you have noticed, the DSL also allows you to remove the messages from
- # matcher. Since it will look for it on I18n yml file.
- #
- # If you want to create a matcher that accepts multile values to be tested,
- # you just need to do:
- #
- # class IncludedMatcher < Remarkable::Base
- # arguments :collection => :values, :as => :value
- # collection_assertion :is_included?
- #
- # protected
- # def is_included?
- # @subject.include?(@value)
- # end
- # end
- #
- # Notice that the :is_included? logic didn't have to change, because Remarkable
- # handle this automatically for you.
+ module DSL
+ # This module is responsable to create a basic matcher structure using a DSL.
#
- module Assertions
-
- def self.included(base) # :nodoc:
- base.extend ClassMethods
+ # A matcher that checks if an element is included in an array can be done
+ # just with:
+ #
+ # class IncludedMatcher < Remarkable::Base
+ # arguments :value
+ # assertion :is_included?
+ #
+ # protected
+ # def is_included?
+ # @subject.include?(@value)
+ # end
+ # end
+ #
+ # As you have noticed, the DSL also allows you to remove the messages from
+ # matcher. Since it will look for it on I18n yml file.
+ #
+ # If you want to create a matcher that accepts multile values to be tested,
+ # you just need to do:
+ #
+ # class IncludedMatcher < Remarkable::Base
+ # arguments :collection => :values, :as => :value
+ # collection_assertion :is_included?
+ #
+ # protected
+ # def is_included?
+ # @subject.include?(@value)
+ # end
+ # end
+ #
+ # Notice that the :is_included? logic didn't have to change, because Remarkable
+ # handle this automatically for you.
+ #
+ module Assertions
+
+ def self.included(base) # :nodoc:
+ base.extend ClassMethods
end
-
- module ClassMethods
+ module ClassMethods
+
protected
- # It sets the arguments your matcher receives on initialization.
- #
+ # It sets the arguments your matcher receives on initialization.
+ #
# == Options
- #
- # * <tt>:collection</tt> - if a collection is expected.
- # * <tt>:as</tt> - how each item of the collection will be available.
- # * <tt>:block</tt> - tell the matcher can receive blocks as argument and store
- # them under the variable given.
- #
- # Note: the expected block cannot have arity 1. This is already reserved
- # for macro configuration.
- #
- # == Examples
- #
- # Let's see for each example how the arguments declarion reflects on
- # the matcher API:
#
- # arguments :assign
- # # Can be called as:
- # #=> should_assign :task
- # #=> should_assign :task, :with => Task.new
- #
- # This is roughly the same as:
- #
+ # * <tt>:collection</tt> - if a collection is expected.
+ # * <tt>:as</tt> - how each item of the collection will be available.
+ # * <tt>:block</tt> - tell the matcher can receive blocks as argument and store
+ # them under the variable given.
+ #
+ # Note: the expected block cannot have arity 1. This is already reserved
+ # for macro configuration.
+ #
+ # == Examples
+ #
+ # Let's see for each example how the arguments declarion reflects on
+ # the matcher API:
+ #
+ # arguments :assign
+ # # Can be called as:
+ # #=> should_assign :task
+ # #=> should_assign :task, :with => Task.new
+ #
+ # This is roughly the same as:
+ #
# def initialize(assign, options = {})
# @assign = name
# @options = options
- # end
- #
- # As you noticed, a matcher can always receive options on initialization.
- # If you have a matcher that accepts only options, for example,
- # have_default_scope you just need to call <tt>arguments</tt>:
- #
- # arguments
- # # Can be called as:
- # #=> should_have_default_scope :limit => 10
- #
- # arguments :collection => :assigns, :as => :assign
- # # Can be called as:
- # #=> should_assign :task1, :task2
- # #=> should_assign :task1, :task2, :with => Task.new
- #
- # arguments :collection => :assigns, :as => :assign, :block => :buildeer
- # # Can be called as:
- # #=> should_assign :task1, :task2
- # #=> should_assign(:task1, :task2){ Task.new }
+ # end
#
- # The block will be available under the instance variable @builder.
- #
- # == I18n
- #
- # All the parameters given to arguments are available for interpolation
- # in I18n. So if you have the following declarion:
- #
- # class InRange < Remarkable::Base
- # arguments :range, :collection => :names, :as => :name
- #
- # You will have {{range}}, {{names}} and {{name}} available for I18n
- # messages:
- #
- # in_range:
- # description: "have {{names}} to be on range {{range}}"
- #
- # Before a collection is sent to I18n, it's transformed to a sentence.
- # So if the following matcher:
- #
- # in_range(2..20, :username, :password)
- #
- # Has the following description:
- #
+ # As you noticed, a matcher can always receive options on initialization.
+ # If you have a matcher that accepts only options, for example,
+ # have_default_scope you just need to call <tt>arguments</tt>:
+ #
+ # arguments
+ # # Can be called as:
+ # #=> should_have_default_scope :limit => 10
+ #
+ # arguments :collection => :assigns, :as => :assign
+ # # Can be called as:
+ # #=> should_assign :task1, :task2
+ # #=> should_assign :task1, :task2, :with => Task.new
+ #
+ # arguments :collection => :assigns, :as => :assign, :block => :buildeer
+ # # Can be called as:
+ # #=> should_assign :task1, :task2
+ # #=> should_assign(:task1, :task2){ Task.new }
+ #
+ # The block will be available under the instance variable @builder.
+ #
+ # == I18n
+ #
+ # All the parameters given to arguments are available for interpolation
+ # in I18n. So if you have the following declarion:
+ #
+ # class InRange < Remarkable::Base
+ # arguments :range, :collection => :names, :as => :name
+ #
+ # You will have {{range}}, {{names}} and {{name}} available for I18n
+ # messages:
+ #
+ # in_range:
+ # description: "have {{names}} to be on range {{range}}"
+ #
+ # Before a collection is sent to I18n, it's transformed to a sentence.
+ # So if the following matcher:
+ #
+ # in_range(2..20, :username, :password)
+ #
+ # Has the following description:
+ #
# "should have username and password in range 2..20"
#
def arguments(*names)
options = names.extract_options!
args = names.dup
@@ -138,147 +138,147 @@
args << 'options={}'
get_options = 'options'
set_collection = ''
end
- if block = options.delete(:block)
- block = :block unless block.is_a?(Symbol)
+ if block = options.delete(:block)
+ block = :block unless block.is_a?(Symbol)
@matcher_arguments[:block] = block
- end
-
- # Blocks are always appended. If they have arity 1, they are used for
- # macro configuration, otherwise, they are stored in the :block variable.
- #
+ end
+
+ # Blocks are always appended. If they have arity 1, they are used for
+ # macro configuration, otherwise, they are stored in the :block variable.
+ #
args << "&block"
assignments = names.map do |name|
"@#{name} = #{name}"
end.join("\n ")
class_eval <<-END, __FILE__, __LINE__
- def initialize(#{args.join(',')})
- _builder, block = block, nil if block && block.arity == 1
- #{assignments}
+ def initialize(#{args.join(',')})
+ _builder, block = block, nil if block && block.arity == 1
+ #{assignments}
#{"@#{block} = block" if block}
@options = default_options.merge(#{get_options})
- #{set_collection}
- run_after_initialize_callbacks
+ #{set_collection}
+ run_after_initialize_callbacks
_builder.call(self) if _builder
end
END
end
- # Declare the assertions that are runned for each element in the collection.
- # It must be used with <tt>arguments</tt> methods in order to work properly.
- #
- # == Examples
- #
- # The example given in <tt>assertions</tt> can be transformed to
- # accept a collection just doing:
- #
- # class IncludedMatcher < Remarkable::Base
- # arguments :collection => :values, :as => :value
- # collection_assertion :is_included?
- #
- # protected
- # def is_included?
- # @subject.include?(@value)
- # end
- # end
- #
- # All further consideration done in <tt>assertions</tt> are also valid here.
- #
+ # Declare the assertions that are runned for each element in the collection.
+ # It must be used with <tt>arguments</tt> methods in order to work properly.
+ #
+ # == Examples
+ #
+ # The example given in <tt>assertions</tt> can be transformed to
+ # accept a collection just doing:
+ #
+ # class IncludedMatcher < Remarkable::Base
+ # arguments :collection => :values, :as => :value
+ # collection_assertion :is_included?
+ #
+ # protected
+ # def is_included?
+ # @subject.include?(@value)
+ # end
+ # end
+ #
+ # All further consideration done in <tt>assertions</tt> are also valid here.
+ #
def collection_assertions(*methods, &block)
define_method methods.last, &block if block_given?
@matcher_collection_assertions += methods
end
alias :collection_assertion :collection_assertions
- # Declares the assertions that are run once per matcher.
- #
- # == Examples
- #
- # A matcher that checks if an element is included in an array can be done
- # just with:
- #
- # class IncludedMatcher < Remarkable::Base
- # arguments :value
- # assertion :is_included?
- #
- # protected
- # def is_included?
- # @subject.include?(@value)
- # end
- # end
- #
- # Whenever the matcher is called, the :is_included? action is automatically
- # triggered. Each assertion must return true or false. In case it's false
- # it will seach for an expectation message on the I18n file. In this
- # case, the error message would be on:
- #
- # included:
- # description: "check {{value}} is included in the array"
- # expectations:
- # is_included: "{{value}} is included in the array"
- #
- # In case of failure, it will output:
- #
- # "Expected {{value}} is included in the array"
- #
- # Notice that on the yml file the question mark is removed for readability.
- #
- # == Shortcut declaration
- #
- # You can shortcut declaration by giving a name and block to assertion
- # method:
- #
- # class IncludedMatcher < Remarkable::Base
- # arguments :value
- #
- # assertion :is_included? do
- # @subject.include?(@value)
- # end
- # end
+ # Declares the assertions that are run once per matcher.
#
- def assertions(*methods, &block)
+ # == Examples
+ #
+ # A matcher that checks if an element is included in an array can be done
+ # just with:
+ #
+ # class IncludedMatcher < Remarkable::Base
+ # arguments :value
+ # assertion :is_included?
+ #
+ # protected
+ # def is_included?
+ # @subject.include?(@value)
+ # end
+ # end
+ #
+ # Whenever the matcher is called, the :is_included? action is automatically
+ # triggered. Each assertion must return true or false. In case it's false
+ # it will seach for an expectation message on the I18n file. In this
+ # case, the error message would be on:
+ #
+ # included:
+ # description: "check {{value}} is included in the array"
+ # expectations:
+ # is_included: "{{value}} is included in the array"
+ #
+ # In case of failure, it will output:
+ #
+ # "Expected {{value}} is included in the array"
+ #
+ # Notice that on the yml file the question mark is removed for readability.
+ #
+ # == Shortcut declaration
+ #
+ # You can shortcut declaration by giving a name and block to assertion
+ # method:
+ #
+ # class IncludedMatcher < Remarkable::Base
+ # arguments :value
+ #
+ # assertion :is_included? do
+ # @subject.include?(@value)
+ # end
+ # end
+ #
+ def assertions(*methods, &block)
if block_given?
- define_method methods.last, &block
- protected methods.last
- end
+ define_method methods.last, &block
+ protected methods.last
+ end
@matcher_single_assertions += methods
end
alias :assertion :assertions
- # Class method that accepts a block or a hash to set matcher's default
- # options. It's called on matcher initialization and stores the default
- # value in the @options instance variable.
- #
- # == Examples
- #
- # default_options do
- # { :name => @subject.name }
- # end
- #
- # default_options :message => :invalid
+ # Class method that accepts a block or a hash to set matcher's default
+ # options. It's called on matcher initialization and stores the default
+ # value in the @options instance variable.
#
+ # == Examples
+ #
+ # default_options do
+ # { :name => @subject.name }
+ # end
+ #
+ # default_options :message => :invalid
+ #
def default_options(hash = {}, &block)
if block_given?
define_method :default_options, &block
else
class_eval "def default_options; #{hash.inspect}; end"
end
- end
+ end
end
-
+
# This method is responsable for connecting <tt>arguments</tt>, <tt>assertions</tt>
- # and <tt>collection_assertions</tt>.
- #
- # It's the one that executes the assertions once, executes the collection
- # assertions for each element in the collection and also responsable to set
- # the I18n messages.
+ # and <tt>collection_assertions</tt>.
#
+ # It's the one that executes the assertions once, executes the collection
+ # assertions for each element in the collection and also responsable to set
+ # the I18n messages.
+ #
def matches?(subject)
@subject = subject
run_before_assert_callbacks
@@ -289,11 +289,11 @@
end
end
protected
- # You can overwrite this instance method to provide default options on
+ # You can overwrite this instance method to provide default options on
# initialization.
#
def default_options
{}
end
@@ -366,24 +366,24 @@
#
def send_methods_and_generate_message(methods) #:nodoc:
methods.each do |method|
bool, hash = send(method)
- unless bool
- parent_scope = matcher_i18n_scope.split('.')
- matcher_name = parent_scope.pop
- lookup = :"expectations.#{method.to_s.gsub(/(\?|\!)$/, '')}"
-
- hash = { :scope => parent_scope, :default => lookup }.merge(hash || {})
- @expectation ||= Remarkable.t "#{matcher_name}.#{lookup}", default_i18n_options.merge(hash)
+ unless bool
+ parent_scope = matcher_i18n_scope.split('.')
+ matcher_name = parent_scope.pop
+ lookup = :"expectations.#{method.to_s.gsub(/(\?|\!)$/, '')}"
+ hash = { :scope => parent_scope, :default => lookup }.merge(hash || {})
+ @expectation ||= Remarkable.t "#{matcher_name}.#{lookup}", default_i18n_options.merge(hash)
+
return false
end
end
return true
- end
-
+ end
+
end
end
end