module RSpec::Matchers::DSL::Macros
def assign_attributes(attr_names)
def assign_attributes(attr_names) attr_reader(*attr_names) private(*attr_names) lambda do |*attr_values| attr_names.zip(attr_values) do |attr_name, attr_value| instance_variable_set(:"@#{attr_name}", attr_value) end end end
def chain(method_name, *attr_names, &definition)
end
end
actual.errors[key] == @message
match do |actual|
end
@message = message
chain :with do |message|
RSpec::Matchers.define :have_errors_on do |key|
@example
be exposed via getters.
arguments in instance variables with those names, and the values will
attribute names instead of a block; the chained method will store its
value(s) for later use (e.g. in `match`), you can provide one or more
In the common case where you just want the chained method to store some
default description and failure message.
hash been enabled, the chained method name and args will be added to the
`include_chain_clauses_in_custom_matcher_descriptions` config option
for you. If the method is invoked and the
return self in order to chain methods together. `chain` handles that
interface. The trick about fluent interfaces is that each method must
Convenience for defining methods on this matcher to create a fluent
def chain(method_name, *attr_names, &definition) unless block_given? ^ attr_names.any? raise ArgumentError, "You must pass either a block or some attribute names (but not both) to `chain`." end definition = assign_attributes(attr_names) if attr_names.any? define_user_override(method_name, definition) do |*args, &block| super(*args, &block) @chained_method_clauses.push([method_name, args]) self end end
def define_user_override(method_name, user_def, &our_def)
(e.g. assigning `@actual`, rescueing errors, etc) and
an override that can provide the wrapped handling
(e.g. for an early guard statement), while allowing us to define
them to use normal method constructs like `return`
This compiles the user block into an actual method, allowing
as an arg, but only if their block's arity can handle it.
of needing to call the user's definition with `@actual`
- Provides a default `our_def` block for the common case
usign the provided `our_def` block.
- Defines an overridden definition for the same method
in the singleton class in which we eval the `define` block.
in @user_method_defs, which is included as an ancestor
- Defines the named method using a user-provided block
Does the following:
def define_user_override(method_name, user_def, &our_def) @user_method_defs.__send__(:define_method, method_name, &user_def) our_def ||= lambda { super(*actual_arg_for(user_def)) } define_method(method_name, &our_def) end
def description(&definition)
- Yield: - actual the actual object (i.e. the value wrapped by `expect`)
def description(&definition) define_user_override(__method__, definition) end
def diffable
Tells the matcher to diff the actual and expected values in the failure
def diffable define_method(:diffable?) { true } end
def failure_message(&definition)
- Yield: - actual the actual object (i.e. the value wrapped by `expect`)
def failure_message(&definition) define_user_override(__method__, definition) end
def failure_message_when_negated(&definition)
- Yield: - actual the actual object (i.e. the value wrapped by `expect`)
def failure_message_when_negated(&definition) define_user_override(__method__, definition) end
def match(options={}, &match_block)
- Yield: - actual the actual value (i.e. the value wrapped by `expect`)
Parameters:
-
options
(Hash
) -- for defining the behavior of the match block.
def match(options={}, &match_block) define_user_override(:matches?, match_block) do |actual| @actual = actual RSpec::Support.with_failure_notifier(RAISE_NOTIFIER) do begin super(*actual_arg_for(match_block)) rescue RSpec::Expectations::ExpectationNotMetError raise if options[:notify_expectation_failures] false end end end end
def match_unless_raises(expected_exception=Exception, &match_block)
- Yield: - actual the actual object (i.e. the value wrapped by `expect`)
def match_unless_raises(expected_exception=Exception, &match_block) define_user_override(:matches?, match_block) do |actual| @actual = actual begin super(*actual_arg_for(match_block)) rescue expected_exception => @rescued_exception false else true end end end
def match_when_negated(options={}, &match_block)
- Yield: - actual the actual value (i.e. the value wrapped by `expect`)
Parameters:
-
options
(Hash
) -- for defining the behavior of the match block.
def match_when_negated(options={}, &match_block) define_user_override(:does_not_match?, match_block) do |actual| begin @actual = actual RSpec::Support.with_failure_notifier(RAISE_NOTIFIER) do super(*actual_arg_for(match_block)) end rescue RSpec::Expectations::ExpectationNotMetError raise if options[:notify_expectation_failures] false end end end
def supports_block_expectations
expectation without declaring this.
Users will not be able to use your matcher in a block
Declares that the matcher can be used in a block expectation.
def supports_block_expectations define_method(:supports_block_expectations?) { true } end