rspec-sleeping_king_studios 2.6.0 → 2.7.0.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/DEVELOPMENT.md +0 -4
- data/README.md +235 -162
- data/lib/rspec/sleeping_king_studios/all.rb +1 -0
- data/lib/rspec/sleeping_king_studios/concerns/include_contract.rb +260 -0
- data/lib/rspec/sleeping_king_studios/contract.rb +165 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/alias_method.rb +8 -2
- data/lib/rspec/sleeping_king_studios/matchers/core/alias_method_matcher.rb +12 -97
- data/lib/rspec/sleeping_king_studios/matchers/core/delegate_method_matcher.rb +8 -1
- data/lib/rspec/sleeping_king_studios/matchers/core/have_aliased_method.rb +12 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_aliased_method_matcher.rb +114 -0
- data/lib/rspec/sleeping_king_studios/version.rb +31 -17
- metadata +9 -4
@@ -0,0 +1,260 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
require 'sleeping_king_studios/tools/toolbelt'
|
6
|
+
|
7
|
+
require 'rspec/sleeping_king_studios/concerns'
|
8
|
+
|
9
|
+
module RSpec::SleepingKingStudios::Concerns
|
10
|
+
# Defines helpers for including reusable contracts in RSpec example groups.
|
11
|
+
#
|
12
|
+
# RSpec contracts are a mechanism for sharing tests between projects. For
|
13
|
+
# example, one library may define an interface or specification for a type of
|
14
|
+
# object, while a second library implements that object. By defining a
|
15
|
+
# contract and sharing that contract as part of the library, the developer
|
16
|
+
# ensures that any object that matches the contract has correctly implemented
|
17
|
+
# and conforms to the interface. This reduces duplication of tests and
|
18
|
+
# provides resiliency as an interface is developed over time and across
|
19
|
+
# versions of the library.
|
20
|
+
#
|
21
|
+
# Mechanically speaking, each contract encapsulates a section of RSpec code.
|
22
|
+
# When the contract is included in a spec, that code is then injected into the
|
23
|
+
# spec. Writing a contract, therefore, is no different than writing any other
|
24
|
+
# RSpec specification - it is only the delivery mechanism that differs. A
|
25
|
+
# contract can be any object that responds to #to_proc; the simplest contract
|
26
|
+
# is therefore a Proc or lambda that contains some RSpec code.
|
27
|
+
#
|
28
|
+
# @example Defining A Contract
|
29
|
+
# module ExampleContracts
|
30
|
+
# # This contract asserts that the object has the Enumerable module as an
|
31
|
+
# # ancestor, and that it responds to the #each method.
|
32
|
+
# SHOULD_BE_ENUMERABLE_CONTRACT = lambda do
|
33
|
+
# it 'should be Enumerable' do
|
34
|
+
# expect(subject).to be_a Enumerable
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# it 'should respond to #each' do
|
38
|
+
# expect(subject).to respond_to(:each).with(0).arguments
|
39
|
+
# end
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# RSpec.describe Array do
|
44
|
+
# extend RSpec::SleepingKingStudios::Concerns::IncludeContract
|
45
|
+
#
|
46
|
+
# include_contract ExampleContracts::SHOULD_BE_ENUMERABLE_CONTRACT
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# RSpec.describe Hash do
|
50
|
+
# extend RSpec::SleepingKingStudios::Concerns::IncludeContract
|
51
|
+
# include ExampleContracts
|
52
|
+
#
|
53
|
+
# include_contract 'should be enumerable'
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# @example Defining A Contract With Parameters
|
57
|
+
# module SerializerContracts
|
58
|
+
# # This contract asserts that the serialized result has the expected
|
59
|
+
# # values.
|
60
|
+
# #
|
61
|
+
# # First, we pass the contract a series of attribute names. These are
|
62
|
+
# # used to assert that the serialized attributes match the values on the
|
63
|
+
# # original object.
|
64
|
+
# #
|
65
|
+
# # Second, we pass the contract a set of attribute names and values.
|
66
|
+
# # These are used to assert that the serialized attributes have the
|
67
|
+
# # specified values.
|
68
|
+
# #
|
69
|
+
# # Finally, we can pass the contract a block, which the contract then
|
70
|
+
# # executes. Note that the block is executed in the context of our
|
71
|
+
# # describe block, and thus can take advantage of our memoized
|
72
|
+
# # #serialized helper method.
|
73
|
+
# SHOULD_SERIALIZE_ATTRIBUTES_CONTRACT = lambda \
|
74
|
+
# do |*attributes, **values, &block|
|
75
|
+
# describe '#serialize' do
|
76
|
+
# let(:serialized) { subject.serialize }
|
77
|
+
#
|
78
|
+
# it { expect(subject).to respond_to(:serialize).with(0).arguments }
|
79
|
+
#
|
80
|
+
# attributes.each do |attribute|
|
81
|
+
# it "should serialize #{attribute}" do
|
82
|
+
# expect(serialized[attribute]).to be == subject[attribute]
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# values.each do |attribute, value|
|
87
|
+
# it "should serialize #{attribute}" do
|
88
|
+
# expect(serialized[attribute]).to be == value
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# instance_exec(&block) if block
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
#
|
96
|
+
# RSpec.describe CaptainPicard do
|
97
|
+
# extend RSpec::SleepingKingStudios::Concerns::IncludeContract
|
98
|
+
# include SerializerContracts
|
99
|
+
#
|
100
|
+
# include_contract 'should serialize attributes',
|
101
|
+
# :name,
|
102
|
+
# :rank,
|
103
|
+
# lights: 4 do
|
104
|
+
# it 'should serialize the catchphrase' do
|
105
|
+
# expect(serialized[:catchphrase]).to be == 'Make it so.'
|
106
|
+
# end
|
107
|
+
# end
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# @see RSpec::SleepingKingStudios::Contract.
|
111
|
+
module IncludeContract
|
112
|
+
class << self
|
113
|
+
# @private
|
114
|
+
def define_contract_method(context:, contract:, name:)
|
115
|
+
method_name = +'rspec_include_contract'
|
116
|
+
method_name << '_' << tools.str.underscore(name) if contract_name?(name)
|
117
|
+
method_name << '_' << tools.str.underscore(SecureRandom.uuid)
|
118
|
+
method_name = method_name.tr(' ', '_').intern
|
119
|
+
|
120
|
+
context.define_singleton_method(method_name, &contract)
|
121
|
+
|
122
|
+
yield method_name
|
123
|
+
ensure
|
124
|
+
if context.singleton_class.respond_to?(method_name)
|
125
|
+
context.singleton_class.remove_method(method_name)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# @private
|
130
|
+
def resolve_contract(context:, contract_or_name:)
|
131
|
+
validate_contract!(contract_or_name)
|
132
|
+
|
133
|
+
return contract_or_name unless contract_name?(contract_or_name)
|
134
|
+
|
135
|
+
contract_name = contract_or_name.to_s
|
136
|
+
contract =
|
137
|
+
resolve_contract_class(context, "#{contract_name} contract") ||
|
138
|
+
resolve_contract_const(context, "#{contract_name} contract") ||
|
139
|
+
resolve_contract_class(context, contract_name) ||
|
140
|
+
resolve_contract_const(context, contract_name)
|
141
|
+
|
142
|
+
return contract if contract
|
143
|
+
|
144
|
+
raise ArgumentError, "undefined contract #{contract_or_name.inspect}"
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def contract?(contract_or_name)
|
150
|
+
contract_or_name.respond_to?(:to_proc)
|
151
|
+
end
|
152
|
+
|
153
|
+
def contract_name?(contract_or_name)
|
154
|
+
contract_or_name.is_a?(String) || contract_or_name.is_a?(Symbol)
|
155
|
+
end
|
156
|
+
|
157
|
+
def resolve_contract_class(context, contract_name)
|
158
|
+
class_name = tools.str.camelize(contract_name.tr(' ', '_'))
|
159
|
+
|
160
|
+
return nil unless context.const_defined?(class_name)
|
161
|
+
|
162
|
+
context.const_get(class_name)
|
163
|
+
end
|
164
|
+
|
165
|
+
def resolve_contract_const(context, contract_name)
|
166
|
+
const_name = tools.str.underscore(contract_name.tr(' ', '_')).upcase
|
167
|
+
|
168
|
+
return nil unless context.const_defined?(const_name)
|
169
|
+
|
170
|
+
context.const_get(const_name)
|
171
|
+
end
|
172
|
+
|
173
|
+
def tools
|
174
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
175
|
+
end
|
176
|
+
|
177
|
+
def validate_contract!(contract_or_name)
|
178
|
+
raise ArgumentError, "contract can't be blank" if contract_or_name.nil?
|
179
|
+
|
180
|
+
if contract_name?(contract_or_name)
|
181
|
+
return unless contract_or_name.to_s.empty?
|
182
|
+
|
183
|
+
raise ArgumentError, "contract can't be blank"
|
184
|
+
end
|
185
|
+
|
186
|
+
return if contract?(contract_or_name)
|
187
|
+
|
188
|
+
raise ArgumentError, 'contract must be a name or respond to #to_proc'
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# As #include_contract, but wraps the contract in a focused example group.
|
193
|
+
#
|
194
|
+
# @see include_contract.
|
195
|
+
def finclude_contract(contract_or_name, *arguments, **keywords, &block)
|
196
|
+
fdescribe '(focused)' do
|
197
|
+
if keywords.empty?
|
198
|
+
include_contract(contract_or_name, *arguments, &block)
|
199
|
+
else
|
200
|
+
include_contract(contract_or_name, *arguments, **keywords, &block)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
# Adds the contract to the example group with the given parameters.
|
206
|
+
#
|
207
|
+
# @overload include_contract(contract, *arguments, **keywords, &block)
|
208
|
+
# @param contract [#to_proc] The contract to include.
|
209
|
+
# @param arguments [Array] The arguments to pass to the contract.
|
210
|
+
# @param keywords [Hash] The keywords to pass to the contract.
|
211
|
+
#
|
212
|
+
# @yield A block passed to the contract.
|
213
|
+
#
|
214
|
+
# @overload include_contract(contract_name, *arguments, **keywords, &block)
|
215
|
+
# @param contract_name [String, Symbol] The name of contract to include.
|
216
|
+
# The contract must be defined as a Class or constant in the same scope,
|
217
|
+
# e.g. include_contract('does something') expects the example group to
|
218
|
+
# define either a DoSomething class or a DO_SOMETHING constant. The name
|
219
|
+
# can optionally be suffixed with "contract", so it will also match a
|
220
|
+
# DoSomethingContract class or a DO_SOMETHING_CONTRACT constant.
|
221
|
+
# @param arguments [Array] The arguments to pass to the contract.
|
222
|
+
# @param keywords [Hash] The keywords to pass to the contract.
|
223
|
+
#
|
224
|
+
# @yield A block passed to the contract.
|
225
|
+
#
|
226
|
+
# @raise ArgumentError
|
227
|
+
def include_contract(contract_or_name, *arguments, **keywords, &block) # rubocop:disable Metrics/MethodLength
|
228
|
+
concern = RSpec::SleepingKingStudios::Concerns::IncludeContract
|
229
|
+
contract = concern.resolve_contract(
|
230
|
+
context: self,
|
231
|
+
contract_or_name: contract_or_name
|
232
|
+
)
|
233
|
+
|
234
|
+
concern.define_contract_method(
|
235
|
+
context: self,
|
236
|
+
contract: contract,
|
237
|
+
name: contract_or_name
|
238
|
+
) do |method_name|
|
239
|
+
if keywords.empty?
|
240
|
+
send(method_name, *arguments, &block)
|
241
|
+
else
|
242
|
+
send(method_name, *arguments, **keywords, &block)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# As #include_contract, but wraps the contract in a skipped example group.
|
248
|
+
#
|
249
|
+
# @see include_contract.
|
250
|
+
def xinclude_contract(contract_or_name, *arguments, **keywords, &block)
|
251
|
+
xdescribe '(skipped)' do
|
252
|
+
if keywords.empty?
|
253
|
+
include_contract(contract_or_name, *arguments, &block)
|
254
|
+
else
|
255
|
+
include_contract(contract_or_name, *arguments, **keywords, &block)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rspec/sleeping_king_studios'
|
4
|
+
require 'rspec/sleeping_king_studios/concerns/include_contract'
|
5
|
+
|
6
|
+
module RSpec::SleepingKingStudios
|
7
|
+
# A Contract wraps RSpec functionality for sharing and reusability.
|
8
|
+
#
|
9
|
+
# An RSpec::SleepingKingStudios::Contract integrates with the
|
10
|
+
# .include_contract class method to share and reuse RSpec examples and
|
11
|
+
# configuration. The major advantage a Contract object provides over using a
|
12
|
+
# Proc is documentation - tools such as YARD do not gracefully handle bare
|
13
|
+
# lambdas, while the functionality and requirements of a Contract can be
|
14
|
+
# specified using standard patterns, such as documenting the parameters passed
|
15
|
+
# to a contract using the #apply method.
|
16
|
+
#
|
17
|
+
# @example Defining A Contract
|
18
|
+
# module ExampleContracts
|
19
|
+
# # This contract asserts that the object has the Enumerable module as an
|
20
|
+
# # ancestor, and that it responds to the #each method.
|
21
|
+
# class ShouldBeEnumerableContract
|
22
|
+
# extend RSpec::SleepingKingStudios::Contract
|
23
|
+
#
|
24
|
+
# # @!method apply(example_group)
|
25
|
+
# # Adds the contract to the example group.
|
26
|
+
#
|
27
|
+
# contract do
|
28
|
+
# it 'should be Enumerable' do
|
29
|
+
# expect(subject).to be_a Enumerable
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# it 'should respond to #each' do
|
33
|
+
# expect(subject).to respond_to(:each).with(0).arguments
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# RSpec.describe Array do
|
40
|
+
# ExampleContracts::SHOULD_BE_ENUMERABLE_CONTRACT.apply(self)
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# RSpec.describe Hash do
|
44
|
+
# extend RSpec::SleepingKingStudios::Concerns::IncludeContract
|
45
|
+
# include ExampleContracts
|
46
|
+
#
|
47
|
+
# include_contract 'should be enumerable'
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# @example Defining A Contract With Parameters
|
51
|
+
# module SerializerContracts
|
52
|
+
# # This contract asserts that the serialized result has the expected
|
53
|
+
# # values.
|
54
|
+
# #
|
55
|
+
# # First, we pass the contract a series of attribute names. These are
|
56
|
+
# # used to assert that the serialized attributes match the values on the
|
57
|
+
# # original object.
|
58
|
+
# #
|
59
|
+
# # Second, we pass the contract a set of attribute names and values.
|
60
|
+
# # These are used to assert that the serialized attributes have the
|
61
|
+
# # specified values.
|
62
|
+
# #
|
63
|
+
# # Finally, we can pass the contract a block, which the contract then
|
64
|
+
# # executes. Note that the block is executed in the context of our
|
65
|
+
# # describe block, and thus can take advantage of our memoized
|
66
|
+
# # #serialized helper method.
|
67
|
+
# class ShouldSerializeAttributesContract
|
68
|
+
# extend RSpec::SleepingKingStudios::Contract
|
69
|
+
#
|
70
|
+
# contract do |*attributes, **values, &block|
|
71
|
+
# describe '#serialize' do
|
72
|
+
# let(:serialized) { subject.serialize }
|
73
|
+
#
|
74
|
+
# it { expect(subject).to respond_to(:serialize).with(0).arguments }
|
75
|
+
#
|
76
|
+
# attributes.each do |attribute|
|
77
|
+
# it "should serialize #{attribute}" do
|
78
|
+
# expect(serialized[attribute]).to be == subject[attribute]
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# values.each do |attribute, value|
|
83
|
+
# it "should serialize #{attribute}" do
|
84
|
+
# expect(serialized[attribute]).to be == value
|
85
|
+
# end
|
86
|
+
# end
|
87
|
+
#
|
88
|
+
# instance_exec(&block) if block
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# RSpec.describe CaptainPicard do
|
94
|
+
# SerializerContracts::ShouldSerializeAttributesContract.apply(
|
95
|
+
# self,
|
96
|
+
# :name,
|
97
|
+
# :rank,
|
98
|
+
# lights: 4) \
|
99
|
+
# do
|
100
|
+
# it 'should serialize the catchphrase' do
|
101
|
+
# expect(serialized[:catchphrase]).to be == 'Make it so.'
|
102
|
+
# end
|
103
|
+
# end
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
# @see RSpec::SleepingKingStudios::Concerns::IncludeContract.
|
107
|
+
module Contract
|
108
|
+
# Adds the contract to the given example group.
|
109
|
+
#
|
110
|
+
# @param example_group [RSpec::Core::ExampleGroup] The example group to
|
111
|
+
# which the contract is applied.
|
112
|
+
# @param arguments [Array] Optional arguments to pass to the contract.
|
113
|
+
# @param keywords [Hash] Optional keywords to pass to the contract.
|
114
|
+
#
|
115
|
+
# @yield A block to pass to the contract.
|
116
|
+
#
|
117
|
+
# @see #to_proc
|
118
|
+
def apply(example_group, *arguments, **keywords, &block)
|
119
|
+
concern = RSpec::SleepingKingStudios::Concerns::IncludeContract
|
120
|
+
|
121
|
+
concern.define_contract_method(
|
122
|
+
context: example_group,
|
123
|
+
contract: self,
|
124
|
+
name: tools.str.underscore(name).gsub('::', '_')
|
125
|
+
) do |method_name|
|
126
|
+
if keywords.empty?
|
127
|
+
example_group.send(method_name, *arguments, &block)
|
128
|
+
else
|
129
|
+
example_group.send(method_name, *arguments, **keywords, &block)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# @overload contract()
|
135
|
+
# @return [Proc, nil] the contract implementation for the class.
|
136
|
+
#
|
137
|
+
# @overload contract()
|
138
|
+
# Sets the contract implementation for the class.
|
139
|
+
#
|
140
|
+
# @yield [*arguments, **keywords, &block] The implementation to
|
141
|
+
# configure for the class.
|
142
|
+
#
|
143
|
+
# @yieldparam arguments [Array] Optional arguments to pass to the
|
144
|
+
# contract.
|
145
|
+
# @yieldparam keywords [Hash] Optional keywords defined for the
|
146
|
+
# contract.
|
147
|
+
# @yieldparam block [Array] A block to pass to the contract.
|
148
|
+
def contract(&block)
|
149
|
+
return @contract = block if block_given?
|
150
|
+
|
151
|
+
@contract
|
152
|
+
end
|
153
|
+
|
154
|
+
# @return [Proc, nil] the contract implementation for the class.
|
155
|
+
def to_proc
|
156
|
+
@contract
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
160
|
+
|
161
|
+
def tools
|
162
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -1,11 +1,17 @@
|
|
1
1
|
# lib/rspec/sleeping_king_studios/matchers/core/alias_method.rb
|
2
2
|
|
3
|
-
require 'rspec/sleeping_king_studios/matchers/core/
|
3
|
+
require 'rspec/sleeping_king_studios/matchers/core/have_aliased_method_matcher'
|
4
4
|
require 'rspec/sleeping_king_studios/matchers/macros'
|
5
5
|
|
6
6
|
module RSpec::SleepingKingStudios::Matchers::Macros
|
7
7
|
# @see RSpec::SleepingKingStudios::Matchers::Core::AliasMethodMatcher#matches?
|
8
8
|
def alias_method expected
|
9
|
-
|
9
|
+
SleepingKingStudios::Tools::CoreTools.deprecate(
|
10
|
+
'#alias_method',
|
11
|
+
message: 'Use #have_aliased_method instead.'
|
12
|
+
)
|
13
|
+
|
14
|
+
RSpec::SleepingKingStudios::Matchers::Core::HaveAliasedMethodMatcher
|
15
|
+
.new expected
|
10
16
|
end # method be_boolean
|
11
17
|
end # module
|
@@ -1,107 +1,22 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'rspec/sleeping_king_studios/matchers/base_matcher'
|
4
3
|
require 'rspec/sleeping_king_studios/matchers/core'
|
4
|
+
require 'rspec/sleeping_king_studios/matchers/core/have_aliased_method_matcher'
|
5
5
|
|
6
6
|
module RSpec::SleepingKingStudios::Matchers::Core
|
7
7
|
# Matcher for testing whether an object aliases a specified method using the
|
8
8
|
# specified other method name.
|
9
9
|
#
|
10
10
|
# @since 2.2.0
|
11
|
-
class AliasMethodMatcher < RSpec::SleepingKingStudios::Matchers::
|
12
|
-
# @param [String, Symbol] expected The name of the method that is expected
|
13
|
-
# to be aliased.
|
14
|
-
def initialize expected
|
15
|
-
@old_method_name = @expected = expected.intern
|
16
|
-
@errors = {}
|
17
|
-
end # method initialize
|
18
|
-
|
19
|
-
# Specifies the name of the new method.
|
20
|
-
#
|
21
|
-
# @param [String, Symbol] new_method_name The method name.
|
22
|
-
#
|
23
|
-
# @return [AliasMethodMatcher] self
|
24
|
-
def as new_method_name
|
25
|
-
@new_method_name = new_method_name
|
26
|
-
|
27
|
-
self
|
28
|
-
end # method as
|
29
|
-
|
30
|
-
# (see BaseMatcher#description)
|
31
|
-
def description
|
32
|
-
str = "alias :#{old_method_name}"
|
33
|
-
|
34
|
-
str << " as #{new_method_name.inspect}" if new_method_name
|
35
|
-
|
36
|
-
str
|
37
|
-
end # method description
|
38
|
-
|
39
|
-
# (see BaseMatcher#failure_message)
|
40
|
-
def failure_message
|
41
|
-
message = "expected #{@actual.inspect} to alias :#{old_method_name}"
|
42
|
-
|
43
|
-
message << " as #{new_method_name.inspect}" if new_method_name
|
44
|
-
|
45
|
-
if @errors[:does_not_respond_to_old_method]
|
46
|
-
message << ", but did not respond to :#{old_method_name}"
|
47
|
-
|
48
|
-
return message
|
49
|
-
end # if
|
50
|
-
|
51
|
-
if @errors[:does_not_respond_to_new_method]
|
52
|
-
message << ", but did not respond to :#{new_method_name}"
|
53
|
-
|
54
|
-
return message
|
55
|
-
end # if
|
56
|
-
|
57
|
-
if @errors[:does_not_alias_method]
|
58
|
-
message <<
|
59
|
-
", but :#{old_method_name} and :#{new_method_name} are different "\
|
60
|
-
"methods"
|
61
|
-
|
62
|
-
return message
|
63
|
-
end # if
|
64
|
-
|
65
|
-
message
|
66
|
-
end # method failure_message
|
67
|
-
|
11
|
+
class AliasMethodMatcher < RSpec::SleepingKingStudios::Matchers::Core::HaveAliasedMethodMatcher
|
68
12
|
# (see BaseMatcher#matches?)
|
69
|
-
def matches?
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
responds_to_methods? && aliases_method?
|
75
|
-
end # method matches?
|
76
|
-
|
77
|
-
private
|
78
|
-
|
79
|
-
attr_reader :old_method_name, :new_method_name
|
80
|
-
|
81
|
-
def aliases_method?
|
82
|
-
unless @actual.method(old_method_name) == @actual.method(new_method_name)
|
83
|
-
@errors[:does_not_alias_method] = true
|
13
|
+
def matches?(actual)
|
14
|
+
SleepingKingStudios::Tools::CoreTools.deprecate(
|
15
|
+
'AliasMethodMatcher',
|
16
|
+
message: 'Use a HaveAliasedMethodMatcher instead.'
|
17
|
+
)
|
84
18
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end # method aliases_method?
|
90
|
-
|
91
|
-
def responds_to_methods?
|
92
|
-
unless @actual.respond_to?(old_method_name)
|
93
|
-
@errors[:does_not_respond_to_old_method] = true
|
94
|
-
|
95
|
-
return false
|
96
|
-
end # unless
|
97
|
-
|
98
|
-
unless @actual.respond_to?(new_method_name)
|
99
|
-
@errors[:does_not_respond_to_new_method] = true
|
100
|
-
|
101
|
-
return false
|
102
|
-
end # unless
|
103
|
-
|
104
|
-
true
|
105
|
-
end # method responds_to_methods?
|
106
|
-
end # class
|
107
|
-
end # module
|
19
|
+
super
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -125,7 +125,14 @@ module RSpec::SleepingKingStudios::Matchers::Core
|
|
125
125
|
|
126
126
|
# (see BaseMatcher#matches?)
|
127
127
|
def matches? actual
|
128
|
-
|
128
|
+
# :nocov:
|
129
|
+
if RUBY_VERSION < '3.0'
|
130
|
+
SleepingKingStudios::Tools::CoreTools.deprecate('DelegateMethodMatcher')
|
131
|
+
else
|
132
|
+
SleepingKingStudios::Tools::CoreTools
|
133
|
+
.new(deprecation_strategy: 'raise')
|
134
|
+
.deprecate('DelegateMethodMatcher')
|
135
|
+
end
|
129
136
|
|
130
137
|
super
|
131
138
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rspec/sleeping_king_studios/matchers/core/have_aliased_method_matcher'
|
4
|
+
require 'rspec/sleeping_king_studios/matchers/macros'
|
5
|
+
|
6
|
+
module RSpec::SleepingKingStudios::Matchers::Macros
|
7
|
+
# @see RSpec::SleepingKingStudios::Matchers::Core::HaveAliasedMethodMatcher#matches?
|
8
|
+
def have_aliased_method(original_name)
|
9
|
+
RSpec::SleepingKingStudios::Matchers::Core::HaveAliasedMethodMatcher
|
10
|
+
.new(original_name)
|
11
|
+
end
|
12
|
+
end
|