rspec-sleeping_king_studios 2.6.0 → 2.7.0.rc.0
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 +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
|