transpec 1.6.1 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,13 +1,19 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'transpec/syntax/mixin/send'
|
5
|
+
require 'transpec/syntax/mixin/have_matcher_owner'
|
3
6
|
require 'transpec/syntax/operator_matcher'
|
4
7
|
|
5
8
|
module Transpec
|
6
9
|
class Syntax
|
7
10
|
module Mixin
|
8
11
|
module ShouldBase
|
9
|
-
|
10
|
-
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
include Send, HaveMatcherOwner
|
14
|
+
|
15
|
+
included do
|
16
|
+
add_dynamic_analysis_request do |rewriter|
|
11
17
|
if OperatorMatcher.dynamic_analysis_target_node?(matcher_node)
|
12
18
|
create_operator_matcher.register_request_for_dynamic_analysis(rewriter)
|
13
19
|
end
|
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
require 'transpec/syntax'
|
4
4
|
require 'transpec/syntax/mixin/should_base'
|
5
|
-
require 'transpec/syntax/mixin/send'
|
6
|
-
require 'transpec/syntax/mixin/have_matcher_owner'
|
7
5
|
require 'transpec/rspec_dsl'
|
8
6
|
require 'transpec/util'
|
9
7
|
require 'active_support/inflector/methods'
|
@@ -11,7 +9,7 @@ require 'active_support/inflector/methods'
|
|
11
9
|
module Transpec
|
12
10
|
class Syntax
|
13
11
|
class OnelinerShould < Syntax
|
14
|
-
include Mixin::ShouldBase,
|
12
|
+
include Mixin::ShouldBase, RSpecDSL, Util
|
15
13
|
|
16
14
|
attr_reader :current_syntax_type
|
17
15
|
|
@@ -114,7 +112,7 @@ module Transpec
|
|
114
112
|
return @example_block_node if instance_variable_defined?(:@example_block_node)
|
115
113
|
|
116
114
|
@example_block_node = @node.each_ancestor_node.find do |node|
|
117
|
-
next false unless node.
|
115
|
+
next false unless node.block_type?
|
118
116
|
send_node = node.children.first
|
119
117
|
receiver_node, method_name, = *send_node
|
120
118
|
next false if receiver_node
|
@@ -93,7 +93,7 @@ module Transpec
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def arg_is_enumerable?
|
96
|
-
return true if arg_node.
|
96
|
+
return true if arg_node.array_type?
|
97
97
|
node_data = runtime_node_data(arg_node)
|
98
98
|
node_data && node_data[:arg_is_enumerable?].result
|
99
99
|
end
|
@@ -101,7 +101,7 @@ module Transpec
|
|
101
101
|
def parenthesize_single_line!(always)
|
102
102
|
if in_explicit_parentheses?(arg_node)
|
103
103
|
remove(range_in_between_selector_and_arg)
|
104
|
-
elsif always || arg_node.
|
104
|
+
elsif always || arg_node.hash_type?
|
105
105
|
replace(range_in_between_selector_and_arg, '(')
|
106
106
|
insert_after(expression_range, ')')
|
107
107
|
elsif range_in_between_selector_and_arg.source.empty?
|
@@ -25,7 +25,7 @@ module Transpec
|
|
25
25
|
|
26
26
|
def positive?
|
27
27
|
@node.each_ancestor_node do |ancestor_node|
|
28
|
-
next unless ancestor_node.
|
28
|
+
next unless ancestor_node.send_type?
|
29
29
|
expectation_method_name = ancestor_node.children[1]
|
30
30
|
return [:should, :to].include?(expectation_method_name)
|
31
31
|
end
|
@@ -38,7 +38,7 @@ module Transpec
|
|
38
38
|
def register_record
|
39
39
|
original_syntax = 'expect { }.not_to raise_error('
|
40
40
|
|
41
|
-
if arg_nodes.first.
|
41
|
+
if arg_nodes.first.const_type?
|
42
42
|
original_syntax << 'SpecificErrorClass'
|
43
43
|
original_syntax << ', message' if arg_nodes.count >= 2
|
44
44
|
else
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'transpec/syntax'
|
4
|
+
require 'transpec/syntax/mixin/send'
|
5
|
+
require 'transpec/syntax/mixin/any_instance_block'
|
6
|
+
|
7
|
+
module Transpec
|
8
|
+
class Syntax
|
9
|
+
class Receive < Syntax
|
10
|
+
include Mixin::Send, Mixin::AnyInstanceBlock
|
11
|
+
|
12
|
+
attr_reader :expectation
|
13
|
+
|
14
|
+
def self.standalone?
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.target_method?(receiver_node, method_name)
|
19
|
+
receiver_node.nil? && method_name == :receive
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(node, expectation, source_rewriter = nil, runtime_data = nil, report = nil)
|
23
|
+
@node = node
|
24
|
+
@expectation = expectation
|
25
|
+
@source_rewriter = source_rewriter
|
26
|
+
@runtime_data = runtime_data
|
27
|
+
@report = report || Report.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def add_receiver_arg_to_any_instance_implementation_block!
|
31
|
+
added = super
|
32
|
+
return unless added
|
33
|
+
@report.records << Record.new(
|
34
|
+
"#{@expectation.method_name}(Klass).to receive(:message) { |arg| }",
|
35
|
+
"#{@expectation.method_name}(Klass).to receive(:message) { |instance, arg| }"
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def any_instance?
|
40
|
+
@expectation.any_instance?
|
41
|
+
end
|
42
|
+
|
43
|
+
def any_instance_block_node
|
44
|
+
return unless any_instance?
|
45
|
+
super || @expectation.block_node
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -2,115 +2,27 @@
|
|
2
2
|
|
3
3
|
require 'transpec/syntax'
|
4
4
|
require 'transpec/util'
|
5
|
-
require 'ast'
|
6
5
|
|
7
6
|
module Transpec
|
8
7
|
class Syntax
|
9
8
|
class RSpecConfigure < Syntax
|
9
|
+
require 'transpec/syntax/rspec_configure/expectations'
|
10
|
+
require 'transpec/syntax/rspec_configure/mocks'
|
11
|
+
|
10
12
|
def self.target_node?(node, runtime_data = nil)
|
11
|
-
return false unless node && node.
|
13
|
+
return false unless node && node.block_type?
|
12
14
|
send_node = node.children.first
|
13
15
|
receiver_node, method_name, *_ = *send_node
|
14
16
|
Util.const_name(receiver_node) == 'RSpec' && method_name == :configure
|
15
17
|
end
|
16
18
|
|
17
|
-
def
|
18
|
-
|
19
|
-
def #{type}_syntaxes
|
20
|
-
#{type}_framework_configuration.syntaxes
|
21
|
-
end
|
22
|
-
|
23
|
-
def modify_#{type}_syntaxes!(syntaxes)
|
24
|
-
#{type}_framework_configuration.modify_syntaxes!(syntaxes)
|
25
|
-
end
|
26
|
-
|
27
|
-
def #{type}_framework_configuration
|
28
|
-
@#{type}_framework_configuration ||=
|
29
|
-
FrameworkConfiguration.new(node, :#{config_method_name}, source_rewriter)
|
30
|
-
end
|
31
|
-
END
|
19
|
+
def expectations
|
20
|
+
@expectations ||= Expectations.new(node, source_rewriter)
|
32
21
|
end
|
33
22
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
class FrameworkConfiguration
|
38
|
-
include ::AST::Sexp
|
39
|
-
|
40
|
-
def initialize(rspec_configure_node, framework_config_method_name, source_rewriter)
|
41
|
-
@rspec_configure_node = rspec_configure_node
|
42
|
-
@framework_config_method_name = framework_config_method_name
|
43
|
-
@source_rewriter = source_rewriter
|
44
|
-
end
|
45
|
-
|
46
|
-
def syntaxes
|
47
|
-
return [] unless syntaxes_node
|
48
|
-
|
49
|
-
case syntaxes_node.type
|
50
|
-
when :sym
|
51
|
-
[syntaxes_node.children.first]
|
52
|
-
when :array
|
53
|
-
syntaxes_node.children.map do |child_node|
|
54
|
-
child_node.children.first
|
55
|
-
end
|
56
|
-
else
|
57
|
-
fail UnknownSyntaxError, "Unknown syntax specification: #{syntaxes_node}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def modify_syntaxes!(syntaxes)
|
62
|
-
unless [Array, Symbol].include?(syntaxes.class)
|
63
|
-
fail ArgumentError, 'Syntaxes must be either an array or a symbol.'
|
64
|
-
end
|
65
|
-
|
66
|
-
@source_rewriter.replace(syntaxes_node.loc.expression, syntaxes.inspect)
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def syntaxes_node
|
72
|
-
return nil unless framework_block_node
|
73
|
-
|
74
|
-
return @syntaxes_node if instance_variable_defined?(:@syntaxes_node)
|
75
|
-
|
76
|
-
framework_config_variable_name = first_block_arg_name(framework_block_node)
|
77
|
-
|
78
|
-
framework_block_node.each_descendent_node do |node|
|
79
|
-
next unless node.type == :send
|
80
|
-
receiver_node, method_name, arg_node, *_ = *node
|
81
|
-
next unless receiver_node == s(:lvar, framework_config_variable_name)
|
82
|
-
next unless method_name == :syntax=
|
83
|
-
return @syntaxes_node = arg_node
|
84
|
-
end
|
85
|
-
|
86
|
-
@syntaxes_node = nil
|
87
|
-
end
|
88
|
-
|
89
|
-
def framework_block_node
|
90
|
-
return @framework_block_node if instance_variable_defined?(:@framework_block_node)
|
91
|
-
|
92
|
-
@framework_block_node = @rspec_configure_node.each_descendent_node.find do |node|
|
93
|
-
next unless node.type == :block
|
94
|
-
send_node = node.children.first
|
95
|
-
receiver_node, method_name, *_ = *send_node
|
96
|
-
next unless receiver_node == s(:lvar, rspec_configure_block_arg_name)
|
97
|
-
method_name == @framework_config_method_name
|
98
|
-
# TODO: Check expectation framework.
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
def rspec_configure_block_arg_name
|
103
|
-
first_block_arg_name(@rspec_configure_node)
|
104
|
-
end
|
105
|
-
|
106
|
-
def first_block_arg_name(block_node)
|
107
|
-
args_node = block_node.children[1]
|
108
|
-
first_arg_node = args_node.children.first
|
109
|
-
first_arg_node.children.first
|
110
|
-
end
|
23
|
+
def mocks
|
24
|
+
@mocks ||= Mocks.new(node, source_rewriter)
|
111
25
|
end
|
112
|
-
|
113
|
-
class UnknownSyntaxError < StandardError; end
|
114
26
|
end
|
115
27
|
end
|
116
28
|
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'transpec/util'
|
4
|
+
require 'ast'
|
5
|
+
|
6
|
+
module Transpec
|
7
|
+
class Syntax
|
8
|
+
class RSpecConfigure
|
9
|
+
class Framework
|
10
|
+
module SyntaxConfiguration
|
11
|
+
def syntaxes
|
12
|
+
return [] unless syntaxes_node
|
13
|
+
|
14
|
+
case syntaxes_node.type
|
15
|
+
when :sym
|
16
|
+
[syntaxes_node.children.first]
|
17
|
+
when :array
|
18
|
+
syntaxes_node.children.map do |child_node|
|
19
|
+
child_node.children.first
|
20
|
+
end
|
21
|
+
else
|
22
|
+
fail UnknownSyntaxError, "Unknown syntax specification: #{syntaxes_node}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def syntaxes=(syntaxes)
|
27
|
+
unless [Array, Symbol].include?(syntaxes.class)
|
28
|
+
fail ArgumentError, 'Syntaxes must be either an array or a symbol.'
|
29
|
+
end
|
30
|
+
|
31
|
+
set_configuration!(:syntax, syntaxes.inspect)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def syntaxes_node
|
37
|
+
return @syntaxes_node if instance_variable_defined?(:@syntaxes_node)
|
38
|
+
|
39
|
+
syntax_setter_node = find_configuration_node(:syntax=)
|
40
|
+
|
41
|
+
@syntaxes_node = if syntax_setter_node
|
42
|
+
syntax_setter_node.children[2]
|
43
|
+
else
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class UnknownSyntaxError < StandardError; end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module Transpec
|
56
|
+
class Syntax
|
57
|
+
class RSpecConfigure
|
58
|
+
class Framework
|
59
|
+
include SyntaxConfiguration, Util, ::AST::Sexp
|
60
|
+
|
61
|
+
def initialize(rspec_configure_node, source_rewriter)
|
62
|
+
@rspec_configure_node = rspec_configure_node
|
63
|
+
@source_rewriter = source_rewriter
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def framework_block_method_name
|
69
|
+
fail NotImplementedError
|
70
|
+
end
|
71
|
+
|
72
|
+
def set_configuration!(config_name, value)
|
73
|
+
setter_node = find_configuration_node("#{config_name}=")
|
74
|
+
|
75
|
+
if setter_node
|
76
|
+
arg_node = setter_node.children[2]
|
77
|
+
@source_rewriter.replace(arg_node.loc.expression, value.to_s)
|
78
|
+
else
|
79
|
+
add_configuration!(config_name, value)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def add_configuration!(config_name, value)
|
84
|
+
block_arg_name = framework_block_arg_name || new_framework_block_arg_name
|
85
|
+
|
86
|
+
lines = [framework_indentation + "#{block_arg_name}.#{config_name} = #{value}"]
|
87
|
+
|
88
|
+
unless framework_block_node
|
89
|
+
indentation = indentation_of_line(@rspec_configure_node) + ' '
|
90
|
+
block_invocation = format(
|
91
|
+
'%s.%s :rspec do |%s|',
|
92
|
+
rspec_configure_block_arg_name, framework_block_method_name, block_arg_name
|
93
|
+
)
|
94
|
+
lines.unshift(indentation + block_invocation)
|
95
|
+
lines << indentation + 'end'
|
96
|
+
end
|
97
|
+
|
98
|
+
block_node = framework_block_node || @rspec_configure_node
|
99
|
+
insertion_position = beginning_of_line_range(block_node.loc.end)
|
100
|
+
|
101
|
+
lines.unshift('') unless (block_node.loc.end.line - block_node.loc.begin.line) <= 1
|
102
|
+
lines.map! { |line| line + "\n" }
|
103
|
+
|
104
|
+
@source_rewriter.insert_before(insertion_position, lines.join(''))
|
105
|
+
end
|
106
|
+
|
107
|
+
def find_configuration_node(configuration_method_name)
|
108
|
+
return nil unless framework_block_node
|
109
|
+
|
110
|
+
configuration_method_name = configuration_method_name.to_sym
|
111
|
+
|
112
|
+
framework_block_node.each_descendent_node.find do |node|
|
113
|
+
next unless node.send_type?
|
114
|
+
receiver_node, method_name, = *node
|
115
|
+
next unless receiver_node == s(:lvar, framework_block_arg_name)
|
116
|
+
method_name == configuration_method_name
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def framework_block_arg_name
|
121
|
+
return nil unless framework_block_node
|
122
|
+
first_block_arg_name(framework_block_node)
|
123
|
+
end
|
124
|
+
|
125
|
+
def framework_block_node
|
126
|
+
return @framework_block_node if instance_variable_defined?(:@framework_block_node)
|
127
|
+
|
128
|
+
@framework_block_node = @rspec_configure_node.each_descendent_node.find do |node|
|
129
|
+
next unless node.block_type?
|
130
|
+
send_node = node.children.first
|
131
|
+
receiver_node, method_name, *_ = *send_node
|
132
|
+
next unless receiver_node == s(:lvar, rspec_configure_block_arg_name)
|
133
|
+
method_name == framework_block_method_name
|
134
|
+
# TODO: Check expectation framework.
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def rspec_configure_block_arg_name
|
139
|
+
first_block_arg_name(@rspec_configure_node)
|
140
|
+
end
|
141
|
+
|
142
|
+
def framework_indentation
|
143
|
+
if framework_block_node
|
144
|
+
indentation_of_line(framework_block_node) + ' '
|
145
|
+
else
|
146
|
+
indentation_of_line(@rspec_configure_node) + ' '
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def new_framework_block_arg_name
|
151
|
+
case rspec_configure_block_arg_name
|
152
|
+
when :rspec then self.class.name.split('::').last.downcase
|
153
|
+
when :c then 'config'
|
154
|
+
else 'c'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def first_block_arg_name(block_node)
|
159
|
+
args_node = block_node.children[1]
|
160
|
+
first_arg_node = args_node.children.first
|
161
|
+
first_arg_node.children.first
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'transpec/syntax/rspec_configure/framework'
|
4
|
+
|
5
|
+
module Transpec
|
6
|
+
class Syntax
|
7
|
+
class RSpecConfigure
|
8
|
+
class Mocks < Framework
|
9
|
+
def framework_block_method_name
|
10
|
+
:mock_with
|
11
|
+
end
|
12
|
+
|
13
|
+
def yield_receiver_to_any_instance_implementation_blocks=(boolean)
|
14
|
+
set_configuration!(:yield_receiver_to_any_instance_implementation_blocks, boolean)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|