rspec-sleeping_king_studios 2.1.1 → 2.2.0.rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -0
  3. data/DEVELOPMENT.md +26 -17
  4. data/LICENSE +1 -1
  5. data/README.md +198 -19
  6. data/lib/rspec/sleeping_king_studios/configuration.rb +63 -2
  7. data/lib/rspec/sleeping_king_studios/examples/property_examples.rb +115 -27
  8. data/lib/rspec/sleeping_king_studios/examples/rspec_matcher_examples.rb +66 -51
  9. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors.rb +8 -269
  10. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors_matcher.rb +268 -0
  11. data/lib/rspec/sleeping_king_studios/matchers/base_matcher.rb +5 -15
  12. data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of.rb +3 -63
  13. data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of_matcher.rb +65 -0
  14. data/lib/rspec/sleeping_king_studios/matchers/built_in/include.rb +3 -108
  15. data/lib/rspec/sleeping_king_studios/matchers/built_in/include_matcher.rb +134 -0
  16. data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to.rb +3 -258
  17. data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to_matcher.rb +116 -0
  18. data/lib/rspec/sleeping_king_studios/matchers/core/alias_method.rb +11 -0
  19. data/lib/rspec/sleeping_king_studios/matchers/core/alias_method_matcher.rb +107 -0
  20. data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean.rb +9 -36
  21. data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean_matcher.rb +37 -0
  22. data/lib/rspec/sleeping_king_studios/matchers/core/construct.rb +3 -210
  23. data/lib/rspec/sleeping_king_studios/matchers/core/construct_matcher.rb +113 -0
  24. data/lib/rspec/sleeping_king_studios/matchers/core/delegate_method.rb +11 -0
  25. data/lib/rspec/sleeping_king_studios/matchers/core/delegate_method_matcher.rb +311 -0
  26. data/lib/rspec/sleeping_king_studios/matchers/core/have_constant.rb +16 -0
  27. data/lib/rspec/sleeping_king_studios/matchers/core/have_constant_matcher.rb +225 -0
  28. data/lib/rspec/sleeping_king_studios/matchers/core/have_predicate.rb +11 -0
  29. data/lib/rspec/sleeping_king_studios/matchers/core/have_predicate_matcher.rb +97 -0
  30. data/lib/rspec/sleeping_king_studios/matchers/core/have_property.rb +3 -104
  31. data/lib/rspec/sleeping_king_studios/matchers/core/have_property_matcher.rb +108 -0
  32. data/lib/rspec/sleeping_king_studios/matchers/core/have_reader.rb +3 -74
  33. data/lib/rspec/sleeping_king_studios/matchers/core/have_reader_matcher.rb +96 -0
  34. data/lib/rspec/sleeping_king_studios/matchers/core/have_writer.rb +4 -59
  35. data/lib/rspec/sleeping_king_studios/matchers/core/have_writer_matcher.rb +55 -0
  36. data/lib/rspec/sleeping_king_studios/matchers/description.rb +62 -0
  37. data/lib/rspec/sleeping_king_studios/matchers/macros.rb +32 -0
  38. data/lib/rspec/sleeping_king_studios/matchers/shared/match_parameters.rb +168 -66
  39. data/lib/rspec/sleeping_king_studios/matchers/shared/match_property.rb +25 -0
  40. data/lib/rspec/sleeping_king_studios/matchers.rb +0 -4
  41. data/lib/rspec/sleeping_king_studios/support/method_signature.rb +51 -0
  42. data/lib/rspec/sleeping_king_studios/support/method_signature_expectation.rb +158 -0
  43. data/lib/rspec/sleeping_king_studios/support.rb +9 -0
  44. data/lib/rspec/sleeping_king_studios/version.rb +10 -4
  45. metadata +46 -30
@@ -0,0 +1,225 @@
1
+ # lib/rspec/sleeping_king_studios/matchers/core/have_constant_matcher.rb
2
+
3
+ require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/core'
5
+ require 'sleeping_king_studios/tools/array_tools'
6
+
7
+ module RSpec::SleepingKingStudios::Matchers::Core
8
+ # Matcher for testing whether an object has a specific constant. Includes
9
+ # functionality for testing the value of the constant and whether the
10
+ # constant is immutable.
11
+ #
12
+ # @since 2.2.0
13
+ class HaveConstantMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
14
+ # @param [String, Symbol] expected The name of the constant to check for on
15
+ # the actual object.
16
+ def initialize expected
17
+ @expected = expected.intern
18
+ end # method initialize
19
+
20
+ # (see BaseMatcher#description)
21
+ def description
22
+ message =
23
+ "have #{@immutable ? 'immutable ' : ''}constant #{@expected.inspect}"
24
+
25
+ message << ' with value ' << value_to_string if @value_set
26
+
27
+ message
28
+ end # method description
29
+
30
+ # (see BaseMatcher#failure_message)
31
+ def failure_message
32
+ message = super
33
+
34
+ messages = []
35
+
36
+ if @errors[:does_not_define_constants]
37
+ message <<
38
+ ", but #{@actual.inspect} does not respond to ::const_defined?"
39
+
40
+ return message
41
+ end # if
42
+
43
+ if @errors[:constant_is_not_defined]
44
+ message <<
45
+ ", but #{@actual.inspect} does not define constant #{@expected.inspect}"
46
+
47
+ return message
48
+ end # if
49
+
50
+ if hsh = @errors[:value_does_not_match]
51
+ messages <<
52
+ "constant #{@expected.inspect} has value #{hsh[:received].inspect}"
53
+ end # if
54
+
55
+ if hsh = @errors[:value_is_mutable]
56
+ messages <<
57
+ "the value of #{@expected.inspect} was mutable"
58
+ end # if
59
+
60
+ unless messages.empty?
61
+ tools = ::SleepingKingStudios::Tools::ArrayTools
62
+
63
+ message << ', but ' << tools.humanize_list(messages)
64
+ end # unless
65
+
66
+ message
67
+ end # method failure_message
68
+
69
+ # (see BaseMatcher#failure_message_when_negated)
70
+ def failure_message_when_negated
71
+ message = super
72
+
73
+ message <<
74
+ ", but #{@actual.inspect} defines constant #{@expected.inspect} with "\
75
+ "value #{actual.const_get(@expected).inspect}"
76
+
77
+ message
78
+ end # method failure_message
79
+
80
+ # Checks if the object has a constant :expected. Additionally, if a
81
+ # value expectation is set, compares the value of #expected to the
82
+ # specified value and checks the mutability of the constant.
83
+ #
84
+ # @param [Object] actual The object to check.
85
+ #
86
+ # @return [Boolean] true If the object has a constant :expected and matches
87
+ # the value and mutability expectations (if any); otherwise false.
88
+ def matches? actual
89
+ super
90
+
91
+ @errors = {}
92
+
93
+ return false unless has_constant?
94
+
95
+ matches_constant? :all?
96
+ end # method matches?
97
+
98
+ # (see BaseMatcher#does_not_match?)
99
+ def does_not_match? actual
100
+ super
101
+
102
+ @errors = {}
103
+
104
+ !has_constant?
105
+ end # method does_not_match?
106
+
107
+ # Sets a mutability expectation. The matcher will determine whether the
108
+ # value of the constant is mutable. Values of `nil`, `false`, `true` are
109
+ # always immutable, as are `Numeric` and `Symbol` primitives. `Array`
110
+ # values must be frozen and all array items must be immutable. `Hash`
111
+ # values must be frozen and all hash keys and values must be immutable.
112
+ #
113
+ # @return [HaveConstantMatcher] self
114
+ def immutable
115
+ @immutable = true
116
+
117
+ self
118
+ end # method immutable
119
+
120
+ # @return [Boolean] True if a mutability expectation is set, otherwise
121
+ # false.
122
+ def immutable?
123
+ !!@immutable
124
+ end # method immutable
125
+
126
+ # Sets a value expectation. The matcher will compare the value of the
127
+ # constant with the specified value.
128
+ #
129
+ # @param [Object] value The value to compare.
130
+ #
131
+ # @return [HaveConstantMatcher] self
132
+ def with value
133
+ @value = value
134
+ @value_set = true
135
+ self
136
+ end # method with
137
+ alias_method :with_value, :with
138
+
139
+ private
140
+
141
+ def has_constant?
142
+ unless actual.respond_to?(:const_defined?)
143
+ @errors[:does_not_define_constants] = true
144
+
145
+ return false
146
+ end # unless
147
+
148
+ unless actual.const_defined?(@expected)
149
+ @errors[:constant_is_not_defined] = true
150
+
151
+ return false
152
+ end # unless
153
+
154
+ true
155
+ end # method has_constant?
156
+
157
+ def immutable_value?
158
+ return true unless @immutable
159
+
160
+ actual_value = actual.const_get(@expected)
161
+
162
+ if mutable?(actual_value)
163
+ @errors[:value_is_mutable] = true
164
+
165
+ return false
166
+ end # if
167
+
168
+ true
169
+ end # method immutable_value
170
+
171
+ def matches_constant? filter
172
+ [ matches_constant_value?,
173
+ immutable_value?
174
+ ].send(filter) { |bool| bool }
175
+ end # method matches_constant?
176
+
177
+ def matches_constant_value?
178
+ return true unless @value_set
179
+
180
+ actual_value = actual.const_get(@expected)
181
+ match = (@value.respond_to?(:matches?) && @value.respond_to?(:description)) ?
182
+ @value.matches?(actual_value) :
183
+ @value == actual_value
184
+
185
+ unless match
186
+ @errors[:value_does_not_match] = {
187
+ :expected => @value,
188
+ :received => actual_value
189
+ } # end hash
190
+
191
+ return false
192
+ end # unless
193
+
194
+ true
195
+ end # method matches_constant_value?
196
+
197
+ def mutable? value
198
+ case value
199
+ when nil, false, true, Numeric, Symbol
200
+ false
201
+ when Array
202
+ return true unless value.frozen?
203
+
204
+ value.reduce(false) { |memo, item| memo || mutable?(item) }
205
+ when Hash
206
+ return true unless value.frozen?
207
+
208
+ (value.keys + value.values).reduce(false) { |memo, item| memo || mutable?(item) }
209
+ else
210
+ !value.frozen?
211
+ end # case
212
+ end # method mutable?
213
+
214
+ # Formats the expected value as a human-readable string. If the value looks
215
+ # like an RSpec matcher (it responds to :matches? and :description), calls
216
+ # value#description; otherwise calls value#inspect.
217
+ #
218
+ # @return [String] the value as a human-readable string.
219
+ def value_to_string
220
+ return @value.description if @value.respond_to?(:matches?) && @value.respond_to?(:description)
221
+
222
+ @value.inspect
223
+ end # method value_to_string
224
+ end # class
225
+ end # module
@@ -0,0 +1,11 @@
1
+ # lib/rspec/sleeping_king_studios/matchers/core/have_predicate.rb
2
+
3
+ require 'rspec/sleeping_king_studios/matchers/core/have_predicate_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/macros'
5
+
6
+ module RSpec::SleepingKingStudios::Matchers::Macros
7
+ # @see RSpec::SleepingKingStudios::Matchers::Core::HavePredicateMatcher#matches?
8
+ def have_predicate expected
9
+ RSpec::SleepingKingStudios::Matchers::Core::HavePredicateMatcher.new expected
10
+ end # method have_reader
11
+ end # module
@@ -0,0 +1,97 @@
1
+ # lib/rspec/sleeping_king_studios/matchers/core/have_predicate_matcher.rb
2
+
3
+ require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/core'
5
+ require 'rspec/sleeping_king_studios/matchers/core/be_boolean_matcher'
6
+ require 'rspec/sleeping_king_studios/matchers/shared/match_property'
7
+
8
+ module RSpec::SleepingKingStudios::Matchers::Core
9
+ # Matcher for testing whether an object has a specific predicate, e.g.
10
+ # responds to :property?.
11
+ #
12
+ # @since 2.2.0
13
+ class HavePredicateMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
14
+ include RSpec::SleepingKingStudios::Matchers::Shared::MatchProperty
15
+
16
+ # Generates a description of the matcher expectation.
17
+ #
18
+ # @return [String] The matcher description.
19
+ def description
20
+ "have predicate :#{@expected}"
21
+ end # method description
22
+
23
+ # @param [String, Symbol] expected The predicate to check for on the actual
24
+ # object.
25
+ def initialize expected
26
+ @expected = expected.to_s.gsub(/\?$/, '').intern
27
+
28
+ apply_boolean_expectation if strict_matching?
29
+ end # method initialize
30
+
31
+ # Checks if the object responds to #expected?. Additionally, if a value
32
+ # expectation is set, compares the value of #expected to the specified
33
+ # value.
34
+ #
35
+ # @param [Object] actual The object to check.
36
+ #
37
+ # @return [Boolean] true If the object responds to #expected and matches
38
+ # the value expectation (if any); otherwise false.
39
+ def matches? actual
40
+ super
41
+
42
+ responds_to_predicate? && matches_predicate_value?
43
+ end # method matches?
44
+
45
+ # Sets a value expectation. The matcher will compare the value from
46
+ # #property? with the specified value.
47
+ #
48
+ # @param [Object] value The value to compare.
49
+ #
50
+ # @return [HaveReaderMatcher] self
51
+ def with_value value
52
+ if strict_matching? && !(value === true || value === false)
53
+ raise ArgumentError.new 'predicate must return true or false'
54
+ end # if
55
+
56
+ @value = value
57
+ @value_set = true
58
+ self
59
+ end # method with
60
+ alias_method :with, :with_value
61
+
62
+ # (see BaseMatcher#failure_message)
63
+ def failure_message
64
+ message = "expected #{@actual.inspect} to respond to :#{@expected}?"
65
+ message << " and return #{value_to_string}" if @value_set
66
+
67
+ if !@matches_predicate
68
+ message << ", but did not respond to :#{@expected}?"
69
+ elsif !@matches_predicate_value
70
+ message << ", but returned #{@actual.send(:"#{@expected}?").inspect}"
71
+ end # if-elsif
72
+
73
+ message
74
+ end # method failure_message
75
+
76
+ # (see BaseMatcher#failure_message_when_negated)
77
+ def failure_message_when_negated
78
+ message = "expected #{@actual.inspect} not to respond to :#{@expected}?"
79
+ message << " and return #{value_to_string}" if @value_set
80
+ message
81
+ end # method failure_message
82
+
83
+ private
84
+
85
+ def apply_boolean_expectation
86
+ matcher = BeBooleanMatcher.new
87
+ aliased = RSpec::Matchers::AliasedMatcher.new matcher, ->(str) { 'true or false' }
88
+
89
+ @value = aliased
90
+ @value_set = true
91
+ end # method apply_boolean_expectation
92
+
93
+ def strict_matching?
94
+ RSpec.configure { |config| config.sleeping_king_studios.matchers }.strict_predicate_matching
95
+ end # method strict_matching?
96
+ end # class
97
+ end # module
@@ -1,110 +1,9 @@
1
1
  # lib/rspec/sleeping_king_studios/matchers/core/have_property.rb
2
2
 
3
- require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
- require 'rspec/sleeping_king_studios/matchers/core'
5
- require 'rspec/sleeping_king_studios/matchers/shared/match_property'
3
+ require 'rspec/sleeping_king_studios/matchers/core/have_property_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/macros'
6
5
 
7
- module RSpec::SleepingKingStudios::Matchers::Core
8
- # Matcher for testing whether an object has a specific property, e.g.
9
- # responds to #property and #property= and has the specified value for
10
- # #property.
11
- #
12
- # @since 1.0.0
13
- class HavePropertyMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
14
- include RSpec::SleepingKingStudios::Matchers::Shared::MatchProperty
15
-
16
- # (see BaseMatcher#description)
17
- def description
18
- value_message = value_to_string
19
- "have property :#{@expected}#{@value_set ? " with value #{value_message}" : ''}"
20
- end # method description
21
-
22
- # @param [String, Symbol] expected The property to check for on the actual
23
- # object.
24
- def initialize expected
25
- @expected = expected.intern
26
- end # method initialize
27
-
28
- # (see BaseMatcher#does_not_match?)
29
- def does_not_match? actual
30
- super
31
-
32
- matches_property?(:none?)
33
- end # method does_not_match?
34
-
35
- # Checks if the object responds to #expected and #expected=. Additionally,
36
- # if a value expectation is set, compares the result of calling :expected
37
- # to the value.
38
- #
39
- # @param [Object] actual The object to check.
40
- #
41
- # @return [Boolean] true If the object responds to #expected and
42
- # #expected= and matches the value expectation (if any); otherwise false.
43
- def matches? actual
44
- super
45
-
46
- matches_property?(:all?)
47
- end # method matches?
48
-
49
- # Sets a value expectation. The matcher will compare the value to the
50
- # result of calling #property.
51
- #
52
- # @param [Object] value The value to set and then compare.
53
- #
54
- # @return [HavePropertyMatcher] self
55
- def with value
56
- @value = value
57
- @value_set = true
58
- self
59
- end # method with
60
- alias_method :with_value, :with
61
-
62
- # (see BaseMatcher#failure_message)
63
- def failure_message
64
- methods = []
65
- methods << ":#{@expected}" unless @matches_reader
66
- methods << ":#{@expected}=" unless @matches_writer
67
-
68
- message = "expected #{@actual.inspect} to respond to :#{@expected} and :#{@expected}="
69
- message << " and return #{value_to_string}" if @value_set
70
-
71
- errors = []
72
- errors << "did not respond to #{methods.join " or "}" unless methods.empty?
73
- errors << "returned #{@actual.send(@expected).inspect}" unless @matches_reader_value || !@value_set
74
-
75
- message << ", but #{errors.join(" and ")}"
76
- message
77
- end # failure_message
78
-
79
- # (see BaseMatcher#failure_message_when_negated)
80
- def failure_message_when_negated
81
- methods = []
82
- methods << ":#{@expected}" if @matches_reader
83
- methods << ":#{@expected}=" if @matches_writer
84
-
85
- message = "expected #{@actual.inspect} not to respond to :#{@expected} or :#{@expected}="
86
- message << " and return #{value_to_string}" if @value_set
87
-
88
- errors = []
89
- errors << "responded to #{methods.join " and "}" unless methods.empty?
90
- errors << "returned #{@actual.send(@expected).inspect}" if @matches_reader_value
91
-
92
- message << ", but #{errors.join(" and ")}"
93
- message
94
- end # failure_message_when_negated
95
-
96
- private
97
-
98
- def matches_property? filter
99
- [ responds_to_reader?,
100
- responds_to_writer?,
101
- matches_reader_value?
102
- ].send(filter) { |bool| bool }
103
- end # method matches_property?
104
- end # class
105
- end # module
106
-
107
- module RSpec::SleepingKingStudios::Matchers
6
+ module RSpec::SleepingKingStudios::Matchers::Macros
108
7
  # @see RSpec::SleepingKingStudios::Matchers::Core::HavePropertyMatcher#matches?
109
8
  def have_property expected
110
9
  RSpec::SleepingKingStudios::Matchers::Core::HavePropertyMatcher.new expected
@@ -0,0 +1,108 @@
1
+ # lib/rspec/sleeping_king_studios/matchers/core/have_property_matcher.rb
2
+
3
+ require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/core'
5
+ require 'rspec/sleeping_king_studios/matchers/shared/match_property'
6
+
7
+ module RSpec::SleepingKingStudios::Matchers::Core
8
+ # Matcher for testing whether an object has a specific property, e.g.
9
+ # responds to #property and #property= and has the specified value for
10
+ # #property.
11
+ #
12
+ # @since 1.0.0
13
+ class HavePropertyMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
14
+ include RSpec::SleepingKingStudios::Matchers::Shared::MatchProperty
15
+
16
+ # (see BaseMatcher#description)
17
+ def description
18
+ value_message = value_to_string
19
+ "have property :#{@expected}#{@value_set ? " with value #{value_message}" : ''}"
20
+ end # method description
21
+
22
+ # @param [String, Symbol] expected The property to check for on the actual
23
+ # object.
24
+ def initialize expected
25
+ @expected = expected.intern
26
+ end # method initialize
27
+
28
+ # (see BaseMatcher#does_not_match?)
29
+ def does_not_match? actual
30
+ super
31
+
32
+ matches_property?(:none?)
33
+ end # method does_not_match?
34
+
35
+ # Checks if the object responds to #expected and #expected=. Additionally,
36
+ # if a value expectation is set, compares the result of calling :expected
37
+ # to the value.
38
+ #
39
+ # @param [Object] actual The object to check.
40
+ #
41
+ # @return [Boolean] true If the object responds to #expected and
42
+ # #expected= and matches the value expectation (if any); otherwise false.
43
+ def matches? actual
44
+ super
45
+
46
+ matches_property?(:all?)
47
+ end # method matches?
48
+
49
+ # Sets a value expectation. The matcher will compare the value to the
50
+ # result of calling #property.
51
+ #
52
+ # @param [Object] value The value to set and then compare.
53
+ #
54
+ # @return [HavePropertyMatcher] self
55
+ def with value
56
+ @value = value
57
+ @value_set = true
58
+ self
59
+ end # method with
60
+ alias_method :with_value, :with
61
+
62
+ # (see BaseMatcher#failure_message)
63
+ def failure_message
64
+ methods = []
65
+ methods << ":#{@expected}" unless @matches_reader
66
+ methods << ":#{@expected}=" unless @matches_writer
67
+
68
+ message = "expected #{@actual.inspect} to respond to :#{@expected} and :#{@expected}="
69
+ message << " and return #{value_to_string}" if @value_set
70
+
71
+ errors = []
72
+ errors << "did not respond to #{methods.join " or "}" unless methods.empty?
73
+
74
+ if @matches_reader
75
+ errors << "returned #{@actual.send(@expected).inspect}" unless @matches_reader_value || !@value_set
76
+ end # if
77
+
78
+ message << ", but #{errors.join(" and ")}"
79
+ message
80
+ end # failure_message
81
+
82
+ # (see BaseMatcher#failure_message_when_negated)
83
+ def failure_message_when_negated
84
+ methods = []
85
+ methods << ":#{@expected}" if @matches_reader
86
+ methods << ":#{@expected}=" if @matches_writer
87
+
88
+ message = "expected #{@actual.inspect} not to respond to :#{@expected} or :#{@expected}="
89
+ message << " and return #{value_to_string}" if @value_set
90
+
91
+ errors = []
92
+ errors << "responded to #{methods.join " and "}" unless methods.empty?
93
+ errors << "returned #{@actual.send(@expected).inspect}" if @matches_reader_value
94
+
95
+ message << ", but #{errors.join(" and ")}"
96
+ message
97
+ end # failure_message_when_negated
98
+
99
+ private
100
+
101
+ def matches_property? filter
102
+ [ responds_to_reader?,
103
+ responds_to_writer?,
104
+ matches_reader_value?
105
+ ].send(filter) { |bool| bool }
106
+ end # method matches_property?
107
+ end # class
108
+ end # module
@@ -1,80 +1,9 @@
1
1
  # lib/rspec/sleeping_king_studios/matchers/core/have_reader.rb
2
2
 
3
- require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
- require 'rspec/sleeping_king_studios/matchers/core'
5
- require 'rspec/sleeping_king_studios/matchers/shared/match_property'
3
+ require 'rspec/sleeping_king_studios/matchers/core/have_reader_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/macros'
6
5
 
7
- module RSpec::SleepingKingStudios::Matchers::Core
8
- # Matcher for testing whether an object has a specific property reader, e.g.
9
- # responds to :property.
10
- #
11
- # @since 1.0.0
12
- class HaveReaderMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
13
- include RSpec::SleepingKingStudios::Matchers::Shared::MatchProperty
14
-
15
- # (see BaseMatcher#description)
16
- def description
17
- value_message = value_to_string
18
- "have reader :#{@expected}#{@value_set ? " with value #{value_message}" : ''}"
19
- end # method description
20
-
21
- # @param [String, Symbol] expected The property to check for on the actual
22
- # object.
23
- def initialize expected
24
- @expected = expected.intern
25
- end # method initialize
26
-
27
- # Checks if the object responds to #expected. Additionally, if a value
28
- # expectation is set, compares the value of #expected to the specified
29
- # value.
30
- #
31
- # @param [Object] actual The object to check.
32
- #
33
- # @return [Boolean] true If the object responds to #expected and matches
34
- # the value expectation (if any); otherwise false.
35
- def matches? actual
36
- super
37
-
38
- responds_to_reader? && matches_reader_value?
39
- end # method matches?
40
-
41
- # Sets a value expectation. The matcher will compare the value from
42
- # #property with the specified value.
43
- #
44
- # @param [Object] value The value to compare.
45
- #
46
- # @return [HaveReaderMatcher] self
47
- def with value
48
- @value = value
49
- @value_set = true
50
- self
51
- end # method with
52
- alias_method :with_value, :with
53
-
54
- # (see BaseMatcher#failure_message)
55
- def failure_message
56
- message = "expected #{@actual.inspect} to respond to :#{@expected}"
57
- message << " and return #{value_to_string}" if @value_set
58
-
59
- if !@matches_reader
60
- message << ", but did not respond to :#{@expected}"
61
- elsif !@matches_reader_value
62
- message << ", but returned #{@actual.send(@expected).inspect}"
63
- end # if
64
-
65
- message
66
- end # method failure_message
67
-
68
- # (see BaseMatcher#failure_message_when_negated)
69
- def failure_message_when_negated
70
- message = "expected #{@actual.inspect} not to respond to :#{@expected}"
71
- message << " and return #{value_to_string}" if @value_set
72
- message
73
- end # method failure_message
74
- end # class
75
- end # module
76
-
77
- module RSpec::SleepingKingStudios::Matchers
6
+ module RSpec::SleepingKingStudios::Matchers::Macros
78
7
  # @see RSpec::SleepingKingStudios::Matchers::Core::HaveReaderMatcher#matches?
79
8
  def have_reader expected
80
9
  RSpec::SleepingKingStudios::Matchers::Core::HaveReaderMatcher.new expected