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,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
|