transpec 1.6.1 → 1.7.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/.rubocop.yml +0 -4
- data/.travis.yml +2 -1
- data/CHANGELOG.md +4 -0
- data/Guardfile +1 -1
- data/README.md +168 -18
- data/README.md.erb +154 -18
- data/lib/transpec/ast/node.rb +47 -0
- data/lib/transpec/cli.rb +1 -1
- data/lib/transpec/commit_message.rb +11 -1
- data/lib/transpec/configuration.rb +11 -10
- data/lib/transpec/converter.rb +36 -14
- data/lib/transpec/dynamic_analyzer/rewriter.rb +2 -2
- data/lib/transpec/option_parser.rb +11 -0
- data/lib/transpec/report.rb +16 -9
- data/lib/transpec/rspec_version.rb +9 -0
- data/lib/transpec/static_context_inspector.rb +4 -4
- data/lib/transpec/syntax/allow.rb +20 -0
- data/lib/transpec/syntax/example.rb +1 -1
- data/lib/transpec/syntax/expect.rb +5 -20
- data/lib/transpec/syntax/its.rb +2 -8
- data/lib/transpec/syntax/method_stub.rb +72 -37
- data/lib/transpec/syntax/mixin/allow_no_message.rb +8 -17
- data/lib/transpec/syntax/mixin/any_instance_block.rb +34 -0
- data/lib/transpec/syntax/mixin/expect_base.rb +70 -0
- data/lib/transpec/syntax/mixin/expectizable.rb +3 -0
- data/lib/transpec/syntax/mixin/have_matcher_owner.rb +5 -2
- data/lib/transpec/syntax/mixin/monkey_patch.rb +6 -0
- data/lib/transpec/syntax/mixin/{any_instance.rb → monkey_patch_any_instance.rb} +12 -8
- data/lib/transpec/syntax/mixin/send.rb +16 -3
- data/lib/transpec/syntax/mixin/should_base.rb +8 -2
- data/lib/transpec/syntax/oneliner_should.rb +2 -4
- data/lib/transpec/syntax/operator_matcher.rb +2 -2
- data/lib/transpec/syntax/raise_error.rb +2 -2
- data/lib/transpec/syntax/receive.rb +49 -0
- data/lib/transpec/syntax/rspec_configure.rb +8 -96
- data/lib/transpec/syntax/rspec_configure/expectations.rb +15 -0
- data/lib/transpec/syntax/rspec_configure/framework.rb +166 -0
- data/lib/transpec/syntax/rspec_configure/mocks.rb +19 -0
- data/lib/transpec/syntax/should.rb +1 -4
- data/lib/transpec/syntax/should_receive.rb +89 -43
- data/lib/transpec/util.rb +21 -7
- data/lib/transpec/version.rb +2 -2
- data/spec/transpec/ast/node_spec.rb +52 -0
- data/spec/transpec/commit_message_spec.rb +2 -2
- data/spec/transpec/configuration_spec.rb +14 -13
- data/spec/transpec/converter_spec.rb +151 -20
- data/spec/transpec/option_parser_spec.rb +10 -0
- data/spec/transpec/rspec_version_spec.rb +20 -6
- data/spec/transpec/static_context_inspector_spec.rb +2 -2
- data/spec/transpec/syntax/allow_spec.rb +140 -0
- data/spec/transpec/syntax/double_spec.rb +1 -1
- data/spec/transpec/syntax/expect_spec.rb +103 -10
- data/spec/transpec/syntax/have_spec.rb +4 -4
- data/spec/transpec/syntax/method_stub_spec.rb +41 -1
- data/spec/transpec/syntax/operator_matcher_spec.rb +6 -6
- data/spec/transpec/syntax/receive_spec.rb +270 -0
- data/spec/transpec/syntax/rspec_configure_spec.rb +241 -30
- data/spec/transpec/syntax/should_receive_spec.rb +93 -2
- data/spec/transpec/syntax/should_spec.rb +2 -2
- data/spec/transpec/util_spec.rb +2 -6
- data/transpec.gemspec +5 -3
- metadata +37 -14
@@ -1,17 +1,16 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
3
|
require 'transpec/syntax'
|
4
|
-
require 'transpec/syntax/mixin/
|
5
|
-
require 'transpec/syntax/mixin/
|
4
|
+
require 'transpec/syntax/mixin/monkey_patch_any_instance'
|
5
|
+
require 'transpec/syntax/mixin/any_instance_block'
|
6
6
|
require 'transpec/syntax/mixin/allow_no_message'
|
7
|
-
require 'transpec/syntax/mixin/any_instance'
|
8
7
|
require 'transpec/util'
|
9
8
|
require 'English'
|
10
9
|
|
11
10
|
module Transpec
|
12
11
|
class Syntax
|
13
12
|
class MethodStub < Syntax
|
14
|
-
include Mixin::
|
13
|
+
include Mixin::MonkeyPatchAnyInstance, Mixin::AnyInstanceBlock, Mixin::AllowNoMessage, Util
|
15
14
|
|
16
15
|
# rubocop:disable LineLength
|
17
16
|
CLASSES_DEFINING_OWN_STUB_METHOD = [
|
@@ -81,13 +80,17 @@ module Transpec
|
|
81
80
|
register_record(:deprecated)
|
82
81
|
end
|
83
82
|
|
83
|
+
def add_receiver_arg_to_any_instance_implementation_block!
|
84
|
+
super && register_record(:any_instance_block)
|
85
|
+
end
|
86
|
+
|
84
87
|
private
|
85
88
|
|
86
89
|
def replacement_source_and_conversion_type(rspec_version)
|
87
90
|
if method_name == :stub_chain
|
88
91
|
[build_allow_to(:receive_message_chain), :allow_to_receive_message_chain]
|
89
92
|
else
|
90
|
-
if arg_node.
|
93
|
+
if arg_node.hash_type?
|
91
94
|
if rspec_version.receive_messages_available?
|
92
95
|
[build_allow_to(:receive_messages), :allow_to_receive_messages]
|
93
96
|
else
|
@@ -141,7 +144,7 @@ module Transpec
|
|
141
144
|
|
142
145
|
def message_source(node)
|
143
146
|
message_source = node.loc.expression.source
|
144
|
-
message_source.prepend(':') if node.
|
147
|
+
message_source.prepend(':') if node.sym_type? && !message_source.start_with?(':')
|
145
148
|
message_source
|
146
149
|
end
|
147
150
|
|
@@ -154,49 +157,81 @@ module Transpec
|
|
154
157
|
end
|
155
158
|
|
156
159
|
def register_record(conversion_type)
|
157
|
-
|
158
|
-
|
160
|
+
record_class = case conversion_type
|
161
|
+
when :deprecated
|
162
|
+
DeprecatedRecord
|
163
|
+
when :any_instance_block
|
164
|
+
AnyInstanceBlockRecord
|
165
|
+
else
|
166
|
+
AllowRecord
|
167
|
+
end
|
168
|
+
@report.records << record_class.new(self, conversion_type)
|
169
|
+
end
|
170
|
+
|
171
|
+
class AllowRecord < Record
|
172
|
+
def initialize(method_stub, conversion_type)
|
173
|
+
@method_stub = method_stub
|
174
|
+
@conversion_type = conversion_type
|
175
|
+
end
|
159
176
|
|
160
|
-
|
161
|
-
|
162
|
-
|
177
|
+
def original_syntax
|
178
|
+
syntax = @method_stub.any_instance? ? 'Klass.any_instance' : 'obj'
|
179
|
+
syntax << ".#{@method_stub.method_name}"
|
163
180
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
181
|
+
if @method_stub.method_name == :stub_chain
|
182
|
+
syntax << '(:message1, :message2)'
|
183
|
+
else
|
184
|
+
syntax << (@method_stub.arg_node.hash_type? ? '(:message => value)' : '(:message)')
|
185
|
+
end
|
168
186
|
end
|
169
|
-
end
|
170
187
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
188
|
+
def converted_syntax
|
189
|
+
syntax = @method_stub.any_instance? ? 'allow_any_instance_of(Klass)' : 'allow(obj)'
|
190
|
+
syntax << '.to '
|
191
|
+
|
192
|
+
case @conversion_type
|
193
|
+
when :allow_to_receive
|
194
|
+
syntax << 'receive(:message)'
|
195
|
+
syntax << '.and_return(value)' if @method_stub.arg_node.hash_type?
|
196
|
+
when :allow_to_receive_messages
|
197
|
+
syntax << 'receive_messages(:message => value)'
|
198
|
+
when :allow_to_receive_message_chain
|
199
|
+
syntax << 'receive_message_chain(:message1, :message2)'
|
200
|
+
end
|
201
|
+
|
202
|
+
syntax
|
176
203
|
end
|
177
204
|
end
|
178
205
|
|
179
|
-
|
180
|
-
|
181
|
-
|
206
|
+
class DeprecatedRecord < Record
|
207
|
+
def initialize(method_stub, *)
|
208
|
+
@method_stub = method_stub
|
209
|
+
end
|
182
210
|
|
183
|
-
|
184
|
-
|
185
|
-
syntax <<
|
186
|
-
syntax << '.and_return(value)' if arg_node.type == :hash
|
187
|
-
when :allow_to_receive_messages
|
188
|
-
syntax << 'receive_messages(:message => value)'
|
189
|
-
when :allow_to_receive_message_chain
|
190
|
-
syntax << 'receive_message_chain(:message1, :message2)'
|
211
|
+
def original_syntax
|
212
|
+
syntax = @method_stub.any_instance? ? 'Klass.any_instance' : 'obj'
|
213
|
+
syntax << ".#{@method_stub.method_name}(:message)"
|
191
214
|
end
|
192
215
|
|
193
|
-
|
216
|
+
def converted_syntax
|
217
|
+
syntax = 'obj.'
|
218
|
+
syntax << @method_stub.send(:replacement_method_for_deprecated_method)
|
219
|
+
syntax << '(:message)'
|
220
|
+
end
|
194
221
|
end
|
195
222
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
223
|
+
class AnyInstanceBlockRecord < Record
|
224
|
+
def initialize(method_stub, *)
|
225
|
+
@method_stub = method_stub
|
226
|
+
end
|
227
|
+
|
228
|
+
def original_syntax
|
229
|
+
"Klass.any_instance.#{@method_stub.method_name}(:message) { |arg| }"
|
230
|
+
end
|
231
|
+
|
232
|
+
def converted_syntax
|
233
|
+
"Klass.any_instance.#{@method_stub.method_name}(:message) { |instance, arg| }"
|
234
|
+
end
|
200
235
|
end
|
201
236
|
end
|
202
237
|
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'transpec/syntax/mixin/send'
|
3
5
|
require 'ast'
|
4
6
|
|
5
7
|
module Transpec
|
6
8
|
class Syntax
|
7
9
|
module Mixin
|
8
10
|
module AllowNoMessage
|
9
|
-
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
include Send, ::AST::Sexp
|
10
13
|
|
11
14
|
def allow_no_message?
|
12
15
|
any_number_of_times? || at_least_zero?
|
@@ -17,8 +20,6 @@ module Transpec
|
|
17
20
|
remove_at_least_zero!
|
18
21
|
end
|
19
22
|
|
20
|
-
private
|
21
|
-
|
22
23
|
def any_number_of_times?
|
23
24
|
!any_number_of_times_node.nil?
|
24
25
|
end
|
@@ -27,6 +28,8 @@ module Transpec
|
|
27
28
|
!at_least_zero_node.nil?
|
28
29
|
end
|
29
30
|
|
31
|
+
private
|
32
|
+
|
30
33
|
def remove_any_number_of_times!
|
31
34
|
return unless any_number_of_times?
|
32
35
|
remove_dot_and_method!(any_number_of_times_node)
|
@@ -44,31 +47,19 @@ module Transpec
|
|
44
47
|
end
|
45
48
|
|
46
49
|
def any_number_of_times_node
|
47
|
-
|
50
|
+
each_chained_method_node do |chained_node|
|
48
51
|
method_name = chained_node.children[1]
|
49
52
|
return chained_node if method_name == :any_number_of_times
|
50
53
|
end
|
51
54
|
end
|
52
55
|
|
53
56
|
def at_least_zero_node
|
54
|
-
|
57
|
+
each_chained_method_node do |chained_node|
|
55
58
|
_, method_name, arg_node = *chained_node
|
56
59
|
next unless method_name == :at_least
|
57
60
|
return chained_node if arg_node == s(:int, 0)
|
58
61
|
end
|
59
62
|
end
|
60
|
-
|
61
|
-
def each_following_chained_method_node
|
62
|
-
return to_enum(__method__) unless block_given?
|
63
|
-
|
64
|
-
@node.each_ancestor_node.reduce(@node) do |child_node, parent_node|
|
65
|
-
return unless [:send, :block].include?(parent_node.type)
|
66
|
-
return unless parent_node.children.first == child_node
|
67
|
-
yield parent_node, child_node
|
68
|
-
parent_node
|
69
|
-
end
|
70
|
-
nil
|
71
|
-
end
|
72
63
|
end
|
73
64
|
end
|
74
65
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'transpec/syntax/mixin/send'
|
5
|
+
|
6
|
+
module Transpec
|
7
|
+
class Syntax
|
8
|
+
module Mixin
|
9
|
+
module AnyInstanceBlock
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
include Send
|
12
|
+
|
13
|
+
def add_receiver_arg_to_any_instance_implementation_block!
|
14
|
+
return unless any_instance_block_node
|
15
|
+
first_arg_node = any_instance_block_node.children[1].children[0]
|
16
|
+
return unless first_arg_node
|
17
|
+
first_arg_name = first_arg_node.children.first
|
18
|
+
return if first_arg_name == :instance
|
19
|
+
insert_before(first_arg_node.loc.expression, 'instance, ')
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def any_instance_block_node
|
26
|
+
return unless any_instance?
|
27
|
+
each_chained_method_node do |node, _|
|
28
|
+
return node if node.block_type?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'transpec/syntax/mixin/send'
|
5
|
+
require 'transpec/syntax/receive'
|
6
|
+
require 'transpec/util'
|
7
|
+
|
8
|
+
module Transpec
|
9
|
+
class Syntax
|
10
|
+
module Mixin
|
11
|
+
module ExpectBase
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
include Send
|
14
|
+
|
15
|
+
included do
|
16
|
+
add_dynamic_analysis_request do |rewriter|
|
17
|
+
if Receive.dynamic_analysis_target_node?(matcher_node)
|
18
|
+
create_receive_matcher.register_request_for_dynamic_analysis(rewriter)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
alias_method :subject_node, :arg_node
|
23
|
+
alias_method :to_node, :parent_node
|
24
|
+
end
|
25
|
+
|
26
|
+
def current_syntax_type
|
27
|
+
:expect
|
28
|
+
end
|
29
|
+
|
30
|
+
def positive?
|
31
|
+
to_method_name = to_node.children[1]
|
32
|
+
to_method_name == :to
|
33
|
+
end
|
34
|
+
|
35
|
+
def matcher_node
|
36
|
+
to_arg_node = to_node.children[2]
|
37
|
+
if to_arg_node.block_type?
|
38
|
+
to_arg_node.children.first
|
39
|
+
else
|
40
|
+
to_arg_node
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def block_node
|
45
|
+
Util.block_node_taken_by_method(to_node)
|
46
|
+
end
|
47
|
+
|
48
|
+
def subject_range
|
49
|
+
subject_node.loc.expression
|
50
|
+
end
|
51
|
+
|
52
|
+
def receive_matcher
|
53
|
+
return @receive_matcher if instance_variable_defined?(:@receive_matcher)
|
54
|
+
|
55
|
+
@receive_matcher ||= if Receive.conversion_target_node?(matcher_node, @runtime_data)
|
56
|
+
create_receive_matcher
|
57
|
+
else
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def create_receive_matcher
|
65
|
+
Receive.new(matcher_node, self, @source_rewriter, @runtime_data, @report)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -1,11 +1,14 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
+
require 'active_support/concern'
|
3
4
|
require 'transpec/util'
|
4
5
|
|
5
6
|
module Transpec
|
6
7
|
class Syntax
|
7
8
|
module Mixin
|
8
9
|
module Expectizable
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
9
12
|
def wrap_subject_in_expect!
|
10
13
|
wrap_subject_with_method!('expect')
|
11
14
|
end
|
@@ -1,13 +1,16 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
+
require 'active_support/concern'
|
3
4
|
require 'transpec/syntax/have'
|
4
5
|
|
5
6
|
module Transpec
|
6
7
|
class Syntax
|
7
8
|
module Mixin
|
8
9
|
module HaveMatcherOwner
|
9
|
-
|
10
|
-
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
|
12
|
+
included do
|
13
|
+
add_dynamic_analysis_request do |rewriter|
|
11
14
|
if Have.dynamic_analysis_target_node?(matcher_node)
|
12
15
|
create_have_matcher.register_request_for_dynamic_analysis(rewriter)
|
13
16
|
end
|
@@ -1,9 +1,15 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'transpec/syntax/mixin/send'
|
5
|
+
|
3
6
|
module Transpec
|
4
7
|
class Syntax
|
5
8
|
module Mixin
|
6
9
|
module MonkeyPatch
|
10
|
+
extend ActiveSupport::Concern
|
11
|
+
include Send
|
12
|
+
|
7
13
|
def register_request_of_syntax_availability_inspection(rewriter, key, methods)
|
8
14
|
code = "self.class.ancestors.any? { |a| a.name.start_with?('RSpec::') }"
|
9
15
|
|
@@ -1,16 +1,18 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'transpec/syntax/mixin/monkey_patch'
|
3
5
|
require 'ast'
|
4
6
|
|
5
7
|
module Transpec
|
6
8
|
class Syntax
|
7
9
|
module Mixin
|
8
|
-
module
|
9
|
-
|
10
|
+
module MonkeyPatchAnyInstance
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
include MonkeyPatch, ::AST::Sexp
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
key = :any_instance_target_class_name
|
14
|
+
included do
|
15
|
+
add_dynamic_analysis_request do |rewriter|
|
14
16
|
code = <<-END.gsub(/^\s+\|/, '').chomp
|
15
17
|
|if self.class.name == 'RSpec::Mocks::AnyInstance::Recorder'
|
16
18
|
| if respond_to?(:klass)
|
@@ -24,7 +26,7 @@ module Transpec
|
|
24
26
|
| nil
|
25
27
|
|end
|
26
28
|
END
|
27
|
-
rewriter.register_request(subject_node,
|
29
|
+
rewriter.register_request(subject_node, :any_instance_target_class_name, code)
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
@@ -35,6 +37,8 @@ module Transpec
|
|
35
37
|
!node_data[:any_instance_target_class_name].result.nil?
|
36
38
|
end
|
37
39
|
|
40
|
+
private
|
41
|
+
|
38
42
|
def any_instance_target_class_source
|
39
43
|
return nil unless any_instance?
|
40
44
|
|
@@ -46,13 +50,13 @@ module Transpec
|
|
46
50
|
end
|
47
51
|
|
48
52
|
def any_instance_target_node
|
49
|
-
return nil unless subject_node.
|
53
|
+
return nil unless subject_node.send_type?
|
50
54
|
return nil unless subject_node.children.count == 2
|
51
55
|
receiver_node, method_name = *subject_node
|
52
56
|
return nil unless receiver_node
|
53
57
|
return nil unless method_name == :any_instance
|
54
58
|
|
55
|
-
if receiver_node.
|
59
|
+
if receiver_node.const_type? || receiver_node == s(:send, nil, :described_class)
|
56
60
|
receiver_node
|
57
61
|
else
|
58
62
|
nil
|
@@ -14,7 +14,7 @@ module Transpec
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def check_target_node_statically(node)
|
17
|
-
return false unless node && node.
|
17
|
+
return false unless node && node.send_type?
|
18
18
|
receiver_node, method_name, *_ = *node
|
19
19
|
target_method?(receiver_node, method_name)
|
20
20
|
end
|
@@ -44,8 +44,8 @@ module Transpec
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
|
48
|
-
|
47
|
+
included do
|
48
|
+
add_dynamic_analysis_request do |rewriter|
|
49
49
|
if receiver_node
|
50
50
|
target_node = receiver_node
|
51
51
|
target_object_type = :object
|
@@ -107,6 +107,19 @@ module Transpec
|
|
107
107
|
def range_after_arg
|
108
108
|
arg_range.end.join(expression_range.end)
|
109
109
|
end
|
110
|
+
|
111
|
+
def each_chained_method_node
|
112
|
+
return to_enum(__method__) unless block_given?
|
113
|
+
|
114
|
+
@node.each_ancestor_node.reduce(@node) do |child_node, parent_node|
|
115
|
+
return unless [:send, :block].include?(parent_node.type)
|
116
|
+
return unless parent_node.children.first == child_node
|
117
|
+
yield parent_node, child_node
|
118
|
+
parent_node
|
119
|
+
end
|
120
|
+
|
121
|
+
nil
|
122
|
+
end
|
110
123
|
end
|
111
124
|
end
|
112
125
|
end
|