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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +52 -0
- data/DEVELOPMENT.md +26 -17
- data/LICENSE +1 -1
- data/README.md +198 -19
- data/lib/rspec/sleeping_king_studios/configuration.rb +63 -2
- data/lib/rspec/sleeping_king_studios/examples/property_examples.rb +115 -27
- data/lib/rspec/sleeping_king_studios/examples/rspec_matcher_examples.rb +66 -51
- data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors.rb +8 -269
- data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors_matcher.rb +268 -0
- data/lib/rspec/sleeping_king_studios/matchers/base_matcher.rb +5 -15
- data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of.rb +3 -63
- data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of_matcher.rb +65 -0
- data/lib/rspec/sleeping_king_studios/matchers/built_in/include.rb +3 -108
- data/lib/rspec/sleeping_king_studios/matchers/built_in/include_matcher.rb +134 -0
- data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to.rb +3 -258
- data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to_matcher.rb +116 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/alias_method.rb +11 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/alias_method_matcher.rb +107 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean.rb +9 -36
- data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean_matcher.rb +37 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/construct.rb +3 -210
- data/lib/rspec/sleeping_king_studios/matchers/core/construct_matcher.rb +113 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/delegate_method.rb +11 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/delegate_method_matcher.rb +311 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_constant.rb +16 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_constant_matcher.rb +225 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_predicate.rb +11 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_predicate_matcher.rb +97 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_property.rb +3 -104
- data/lib/rspec/sleeping_king_studios/matchers/core/have_property_matcher.rb +108 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_reader.rb +3 -74
- data/lib/rspec/sleeping_king_studios/matchers/core/have_reader_matcher.rb +96 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_writer.rb +4 -59
- data/lib/rspec/sleeping_king_studios/matchers/core/have_writer_matcher.rb +55 -0
- data/lib/rspec/sleeping_king_studios/matchers/description.rb +62 -0
- data/lib/rspec/sleeping_king_studios/matchers/macros.rb +32 -0
- data/lib/rspec/sleeping_king_studios/matchers/shared/match_parameters.rb +168 -66
- data/lib/rspec/sleeping_king_studios/matchers/shared/match_property.rb +25 -0
- data/lib/rspec/sleeping_king_studios/matchers.rb +0 -4
- data/lib/rspec/sleeping_king_studios/support/method_signature.rb +51 -0
- data/lib/rspec/sleeping_king_studios/support/method_signature_expectation.rb +158 -0
- data/lib/rspec/sleeping_king_studios/support.rb +9 -0
- data/lib/rspec/sleeping_king_studios/version.rb +10 -4
- 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/
|
4
|
-
require 'rspec/sleeping_king_studios/matchers/
|
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::
|
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/
|
4
|
-
require 'rspec/sleeping_king_studios/matchers/
|
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::
|
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
|