Module: RSpec::Matchers::Composable
- Included in:
- BuiltIn::BaseMatcher, BuiltIn::RaiseError, BuiltIn::ThrowSymbol, DSL::Matcher
- Defined in:
- lib/rspec/matchers/composable.rb
Overview
Mixin designed to support the composable matcher features of RSpec 3+. Mix it into your custom matcher classes to allow them to be used in a composable fashion.
Defined Under Namespace
Classes: DescribableItem
Class Method Summary collapse
-
.should_enumerate?(item) ⇒ Boolean
private
We should enumerate arrays as long as they are not recursive.
-
.surface_descriptions_in(item) ⇒ Object
Transforms the given data structure (typically a hash or array) into a new data structure that, when
#inspect
is called on it, will provide descriptions of any contained matchers rather than the normal#inspect
output. - .unreadable_io?(object) ⇒ Boolean private
Instance Method Summary collapse
-
#===(value) ⇒ Object
Delegates to
#matches?
. -
#and(matcher) ⇒ Object
(also: #&)
Creates a compound
and
expectation. -
#description_of(object) ⇒ Object
Returns the description of the given object in a way that is aware of composed matchers.
-
#or(matcher) ⇒ Object
(also: #|)
Creates a compound
or
expectation. -
#values_match?(expected, actual) ⇒ Boolean
This provides a generic way to fuzzy-match an expected value against an actual value.
Class Method Details
.should_enumerate?(item) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
We should enumerate arrays as long as they are not recursive.
142 143 144 |
# File 'lib/rspec/matchers/composable.rb', line 142 def should_enumerate?(item) Array === item && item.none? { |subitem| subitem.equal?(item) } end |
.surface_descriptions_in(item) ⇒ Object
Transforms the given data structure (typically a hash or array)
into a new data structure that, when #inspect
is called on it,
will provide descriptions of any contained matchers rather than
the normal #inspect
output.
You are encouraged to use this in your custom matcher's
description
, failure_message
or
failure_message_when_negated
implementation if you are
supporting any arguments which may be a data structure
containing matchers.
98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/rspec/matchers/composable.rb', line 98 def surface_descriptions_in(item) if Matchers.is_a_describable_matcher?(item) DescribableItem.new(item) elsif Hash === item Hash[surface_descriptions_in(item.to_a)] elsif Struct === item || unreadable_io?(item) RSpec::Support::ObjectFormatter.format(item) elsif should_enumerate?(item) item.map { |subitem| surface_descriptions_in(subitem) } else item end end |
.unreadable_io?(object) ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
147 148 149 150 151 152 153 |
# File 'lib/rspec/matchers/composable.rb', line 147 def unreadable_io?(object) return false unless IO === object object.each {} # STDOUT is enumerable but raises an error false rescue IOError true end |
Instance Method Details
#===(value) ⇒ Object
Delegates to #matches?
. Allows matchers to be used in composable
fashion and also supports using matchers in case statements.
45 46 47 |
# File 'lib/rspec/matchers/composable.rb', line 45 def ===(value) matches?(value) end |
#and(matcher) ⇒ Object Also known as: &
The negative form (expect(...).not_to matcher.and other
)
is not supported at this time.
Creates a compound and
expectation. The matcher will
only pass if both sub-matchers pass.
This can be chained together to form an arbitrarily long
chain of matchers.
22 23 24 |
# File 'lib/rspec/matchers/composable.rb', line 22 def and(matcher) BuiltIn::Compound::And.new self, matcher end |
#description_of(object) ⇒ Object
Returns the description of the given object in a way that is
aware of composed matchers. If the object is a matcher with
a description
method, returns the description; otherwise
returns object.inspect
.
You are encouraged to use this in your custom matcher's
description
, failure_message
or
failure_message_when_negated
implementation if you are
supporting matcher arguments.
82 83 84 |
# File 'lib/rspec/matchers/composable.rb', line 82 def description_of(object) RSpec::Support::ObjectFormatter.format(object) end |
#or(matcher) ⇒ Object Also known as: |
The negative form (expect(...).not_to matcher.or other
)
is not supported at this time.
Creates a compound or
expectation. The matcher will
pass if either sub-matcher passes.
This can be chained together to form an arbitrarily long
chain of matchers.
38 39 40 |
# File 'lib/rspec/matchers/composable.rb', line 38 def or(matcher) BuiltIn::Compound::Or.new self, matcher end |
#values_match?(expected, actual) ⇒ Boolean
This provides a generic way to fuzzy-match an expected value against an actual value. It understands nested data structures (e.g. hashes and arrays) and is able to match against a matcher being used as the expected value or within the expected value at any level of nesting.
Within a custom matcher you are encouraged to use this whenever your
matcher needs to match two values, unless it needs more precise semantics.
For example, the eq
matcher does not use this as it is meant to
use ==
(and only ==
) for matching.
66 67 68 69 |
# File 'lib/rspec/matchers/composable.rb', line 66 def values_match?(expected, actual) expected = with_matchers_cloned(expected) Support::FuzzyMatcher.values_match?(expected, actual) end |