Module: RSpec::Matchers::DSL::Macros
Relationships & Source Files | |
Namespace Children | |
Modules:
| |
Extension / Inclusion / Inheritance Descendants | |
Extended In:
| |
Defined in: | rspec-expectations/lib/rspec/matchers/dsl.rb |
Overview
Contains the methods that are available from within the RSpec::Matchers.define ::RSpec::Matchers::DSL
for creating custom matchers.
Constant Summary
-
RAISE_NOTIFIER =
Internal use only
# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 146Proc.new { |err, _opts| raise err }
Instance Method Summary
-
#chain(method_name, *attr_names, &definition)
Convenience for defining methods on this matcher to create a fluent interface.
-
#description {|Object| ... }
Customize the description to use for one-liners.
-
#diffable
Tells the matcher to diff the actual and expected values in the failure message.
-
#failure_message {|Object| ... }
Customizes the failure message to use when this matcher is asked to positively match.
-
#failure_message_when_negated {|Object| ... }
Customize the failure message to use when this matcher is asked to negatively match.
-
#match(options = {}) {|Object| ... }
Stores the block that is used to determine whether this matcher passes or fails.
-
#match_unless_raises(expected_exception = Exception) {|Object| ... }
Use this instead of #match when the block will raise an exception rather than returning false to indicate a failure.
-
#match_when_negated(options = {}) {|Object| ... }
Use this to define the block for a negative expectation (‘expect(…).not_to`) when the positive and negative forms require different handling.
-
#supports_block_expectations
Declares that the matcher can be used in a block expectation.
- #assign_attributes(attr_names) private
-
#define_user_override(method_name, user_def, &our_def)
private
Does the following:
Instance Method Details
#assign_attributes(attr_names) (private)
[ GitHub ]# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 312
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
#chain(method_name, *attr_names, &definition)
Convenience for defining methods on this matcher to create a fluent interface. The trick about fluent interfaces is that each method must return self in order to chain methods together. chain
handles that for you. If the method is invoked and the include_chain_clauses_in_custom_matcher_descriptions
config option hash been enabled, the chained method name and args will be added to the default description and failure message.
In the common case where you just want the chained method to store some value(s) for later use (e.g. in #match), you can provide one or more attribute names instead of a block; the chained method will store its arguments in instance variables with those names, and the values will be exposed via getters.
# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 298
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
#define_user_override(method_name, user_def, &our_def) (private)
Does the following:
-
Defines the named method using a user-provided block in @user_method_defs, which is included as an ancestor in the singleton class in which we eval the RSpec::Matchers::DSL#define block.
-
Defines an overridden definition for the same method usign the provided
our_def
block. -
Provides a default
our_def
block for the common case of needing to call the user’s definition with@actual
as an arg, but only if their block’s arity can handle it.
This compiles the user block into an actual method, allowing them to use normal method constructs like return
(e.g. for an early guard statement), while allowing us to define an override that can provide the wrapped handling (e.g. assigning @actual
, rescueing errors, etc) and can super
to the user’s definition.
# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 346
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
#description {|Object| ... }
Customize the description to use for one-liners. Only use this when the description generated by default doesn’t suit your needs.
# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 253
def description(&definition) define_user_override(__method__, definition) end
#diffable
Tells the matcher to diff the actual and expected values in the failure message.
# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 259
def diffable define_method(:diffable?) { true } end
#failure_message {|Object| ... }
Customizes the failure message to use when this matcher is asked to positively match. Only use this when the message generated by default doesn’t suit your needs.
# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 216
def (&definition) define_user_override(__method__, definition) end
#failure_message_when_negated {|Object| ... }
Customize the failure message to use when this matcher is asked to negatively match. Only use this when the message generated by default doesn’t suit your needs.
# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 235
def (&definition) define_user_override(__method__, definition) end
#match(options = {}) {|Object| ... }
Stores the block that is used to determine whether this matcher passes or fails. The block should return a boolean value. When the matcher is passed to ‘expect(…).to` and the block returns true
, then the expectation passes. Similarly, when the matcher is passed to expect(…).not_to
and the block returns false
, then the expectation passes.
By default the match block will swallow expectation errors (e.g. caused by using an expectation such as ‘expect(1).to eq 2`), if you wish to allow these to bubble up, pass in the option `:notify_expectation_failures => true`.
# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 131
def match(={}, &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 [:notify_expectation_failures] false end end end end
#match_unless_raises(expected_exception = Exception) {|Object| ... }
Use this instead of #match when the block will raise an exception rather than returning false to indicate a failure.
# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 188
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
#match_when_negated(options = {}) {|Object| ... }
Use this to define the block for a negative expectation (‘expect(…).not_to`) when the positive and negative forms require different handling. This is rarely necessary, but can be helpful, for example, when specifying asynchronous processes that require different timeouts.
By default the match block will swallow expectation errors (e.g. caused by using an expectation such as ‘expect(1).to eq 2`), if you wish to allow these to bubble up, pass in the option `:notify_expectation_failures => true`.
# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 160
def match_when_negated(={}, &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 [:notify_expectation_failures] false end end end
#supports_block_expectations
Declares that the matcher can be used in a block expectation. Users will not be able to use your matcher in a block expectation without declaring this. (e.g. ‘expect { do_something }.to matcher`).
# File 'rspec-expectations/lib/rspec/matchers/dsl.rb', line 267
def supports_block_expectations define_method(:supports_block_expectations?) { true } end