transpec 1.5.1 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,18 +5,8 @@ require 'transpec/configuration'
5
5
  require 'transpec/report'
6
6
  require 'transpec/rspec_version'
7
7
  require 'transpec/syntax'
8
- require 'transpec/syntax/be_boolean'
9
- require 'transpec/syntax/be_close'
10
- require 'transpec/syntax/double'
11
- require 'transpec/syntax/example'
12
- require 'transpec/syntax/expect'
13
- require 'transpec/syntax/its'
14
- require 'transpec/syntax/method_stub'
15
- require 'transpec/syntax/oneliner_should'
16
- require 'transpec/syntax/raise_error'
17
- require 'transpec/syntax/rspec_configure'
18
- require 'transpec/syntax/should'
19
- require 'transpec/syntax/should_receive'
8
+
9
+ Transpec::Syntax.require_all
20
10
 
21
11
  module Transpec
22
12
  class Converter < BaseRewriter
@@ -86,7 +76,7 @@ module Transpec
86
76
  else
87
77
  oneliner_should.convert_have_items_to_standard_should!
88
78
  end
89
- elsif @configuration.convert_oneliner? && @rspec_version.one_liner_is_expected_available?
79
+ elsif @configuration.convert_oneliner? && @rspec_version.oneliner_is_expected_available?
90
80
  oneliner_should.expectize!(negative_form, parenthesize)
91
81
  end
92
82
  end
@@ -159,6 +149,11 @@ module Transpec
159
149
  example.convert! if @configuration.convert_deprecated_method?
160
150
  end
161
151
 
152
+ def process_matcher_definition(matcher_definition)
153
+ return unless @rspec_version.non_should_matcher_protocol_available?
154
+ matcher_definition.convert_deprecated_method! if @configuration.convert_deprecated_method?
155
+ end
156
+
162
157
  def process_rspec_configure(rspec_configure)
163
158
  if need_to_modify_expectation_syntax_configuration?(rspec_configure)
164
159
  rspec_configure.modify_expectation_syntaxes!(:expect)
@@ -13,7 +13,6 @@ require 'English'
13
13
 
14
14
  module Transpec
15
15
  class DynamicAnalyzer
16
- EVAL_TARGET_TYPES = [:object, :context]
17
16
  ANALYSIS_METHOD = 'transpec_analysis'
18
17
  HELPER_FILE = 'transpec_analysis_helper.rb'
19
18
  RESULT_FILE = 'transpec_analysis_result.json'
@@ -1,13 +1,19 @@
1
1
  # coding: utf-8
2
2
 
3
3
  require 'transpec/base_rewriter'
4
+ require 'transpec/dynamic_analyzer'
5
+ require 'transpec/syntax'
4
6
  require 'transpec/util'
5
7
 
8
+ Transpec::Syntax.require_all
9
+
6
10
  module Transpec
7
11
  class DynamicAnalyzer
8
12
  class Rewriter < BaseRewriter
9
13
  include Util
10
14
 
15
+ EVAL_TARGET_TYPES = [:object, :context]
16
+
11
17
  def process(ast, source_rewriter)
12
18
  # TODO: Currently multitheading is not considered...
13
19
  clear_requests!
@@ -75,7 +81,6 @@ module Transpec
75
81
  '), self, %s, __FILE__, %d, %d)',
76
82
  hash_literal(analysis_codes), source_range.begin_pos, source_range.end_pos
77
83
  )
78
- rear = "\n" + indentation_of_line(source_range.end) + rear if contain_here_document?(node)
79
84
 
80
85
  [front, rear]
81
86
  end
@@ -1,20 +1,31 @@
1
1
  # coding: utf-8
2
2
 
3
+ # Aliases by Capybara:
4
+ # https://github.com/jnicklas/capybara/blob/2.2.0/lib/capybara/rspec/features.rb
5
+
3
6
  module Transpec
4
7
  module RSpecDSL
5
8
  EXAMPLE_GROUP_METHODS = [
6
9
  :describe, :context,
7
- :shared_examples, :shared_context, :share_examples_for, :shared_examples_for
10
+ :shared_examples, :shared_context, :share_examples_for, :shared_examples_for,
11
+ :feature # Capybara
8
12
  ].freeze
9
13
 
10
14
  EXAMPLE_METHODS = [
11
15
  :example, :it, :specify,
12
16
  :focus, :focused, :fit,
13
- :pending, :xexample, :xit, :xspecify
17
+ :pending, :xexample, :xit, :xspecify,
18
+ :scenario, :xscenario # Capybara
14
19
  ].freeze
15
20
 
16
- HOOK_METHODS = [:before, :after, :around].freeze
21
+ HOOK_METHODS = [
22
+ :before, :after, :around,
23
+ :background # Capybara
24
+ ].freeze
17
25
 
18
- HELPER_METHODS = [:subject, :subject!, :let, :let!].freeze
26
+ HELPER_METHODS = [
27
+ :subject, :subject!, :let, :let!,
28
+ :given, :given! # Capybara
29
+ ].freeze
19
30
  end
20
31
  end
@@ -41,10 +41,11 @@ module Transpec
41
41
  @gem_version.to_s
42
42
  end
43
43
 
44
- define_feature :be_truthy, '2.99.0.beta1'
45
- define_feature :yielded_example, '2.99.0.beta1'
46
- define_feature :one_liner_is_expected, '2.99.0.beta2', except: '3.0.0.beta1'
47
- define_feature :receive_messages, '3.0.0.beta1'
48
- define_feature :receive_message_chain, '3.0.0.beta2'
44
+ define_feature :be_truthy, '2.99.0.beta1'
45
+ define_feature :yielded_example, '2.99.0.beta1'
46
+ define_feature :oneliner_is_expected, '2.99.0.beta2', except: '3.0.0.beta1'
47
+ define_feature :receive_messages, '3.0.0.beta1'
48
+ define_feature :receive_message_chain, '3.0.0.beta2'
49
+ define_feature :non_should_matcher_protocol, '3.0.0.beta2'
49
50
  end
50
51
  end
@@ -8,6 +8,7 @@ module Transpec
8
8
  include RSpecDSL, Util
9
9
 
10
10
  SCOPE_TYPES = [:module, :class, :sclass, :def, :defs, :block].freeze
11
+ TWISTED_SCOPE_TYPES = (SCOPE_TYPES - [:def, :defs]).freeze
11
12
 
12
13
  NON_MONKEY_PATCH_EXPECTATION_AVAILABLE_CONTEXT = [
13
14
  [:example_group, :example],
@@ -41,12 +42,16 @@ module Transpec
41
42
 
42
43
  def scopes
43
44
  @scopes ||= begin
44
- scopes = @node.each_ancestor_node.reverse_each.map { |node| scope_type(node) }
45
+ scopes = valid_ancestor_nodes.reverse_each.map { |node| scope_type(node) }
45
46
  scopes.compact!
46
47
  scopes.extend(ArrayExtension)
47
48
  end
48
49
  end
49
50
 
51
+ def inside_of_example_group?
52
+ scopes.include?(:example_group)
53
+ end
54
+
50
55
  def non_monkey_patch_expectation_available?
51
56
  return @expectation_available if instance_variable_defined?(:@expectation_available)
52
57
  @expectation_available = match_scopes(NON_MONKEY_PATCH_EXPECTATION_AVAILABLE_CONTEXT)
@@ -64,6 +69,25 @@ module Transpec
64
69
 
65
70
  private
66
71
 
72
+ def valid_ancestor_nodes
73
+ valid_nodes = []
74
+
75
+ self_and_ancestor_nodes = [@node] + @node.ancestor_nodes
76
+
77
+ self_and_ancestor_nodes.each_cons(2) do |child, parent|
78
+ valid_nodes << parent unless belong_to_direct_outer_scope?(child)
79
+ end
80
+
81
+ valid_nodes
82
+ end
83
+
84
+ def belong_to_direct_outer_scope?(node)
85
+ return false unless TWISTED_SCOPE_TYPES.include?(node.parent_node.type)
86
+ scope_node = node.parent_node
87
+ return true if node.equal?(scope_node.children[0])
88
+ scope_node.type == :class && node.equal?(scope_node.children[1])
89
+ end
90
+
67
91
  def scope_type(node)
68
92
  return nil unless SCOPE_TYPES.include?(node.type)
69
93
 
@@ -13,6 +13,13 @@ module Transpec
13
13
  all_syntaxes << subclass
14
14
  end
15
15
 
16
+ def require_all
17
+ pattern = File.join(File.dirname(__FILE__), 'syntax', '*.rb')
18
+ Dir.glob(pattern) do |path|
19
+ require path
20
+ end
21
+ end
22
+
16
23
  def all_syntaxes
17
24
  @subclasses ||= []
18
25
  end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+
3
+ require 'transpec/syntax'
4
+ require 'transpec/syntax/mixin/send'
5
+
6
+ module Transpec
7
+ class Syntax
8
+ class MatcherDefinition < Syntax
9
+ include Mixin::Send
10
+
11
+ CONVERSION_CORRESPONDENCE = {
12
+ match_for_should: :match,
13
+ match_for_should_not: :match_when_negated,
14
+ failure_message_for_should: :failure_message,
15
+ failure_message_for_should_not: :failure_message_when_negated
16
+ }
17
+
18
+ def self.target_method?(receiver_node, method_name)
19
+ receiver_node.nil? && CONVERSION_CORRESPONDENCE.keys.include?(method_name)
20
+ end
21
+
22
+ def convert_deprecated_method!
23
+ replacement_method_name = CONVERSION_CORRESPONDENCE[method_name].to_s
24
+ replace(selector_range, replacement_method_name)
25
+
26
+ @report.records << Record.new("#{method_name} { }", "#{replacement_method_name} { }")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -20,7 +20,7 @@ module Transpec
20
20
  end
21
21
 
22
22
  def target_method?(receiver_node, method_name)
23
- NotImplementedError
23
+ fail NotImplementedError
24
24
  end
25
25
 
26
26
  def check_target_node_dynamically(node, runtime_data)
data/lib/transpec/util.rb CHANGED
@@ -47,13 +47,11 @@ module Transpec
47
47
 
48
48
  def here_document?(node)
49
49
  return false unless [:str, :dstr].include?(node.type)
50
- map = node.loc
51
- return false if !map.respond_to?(:begin) || map.begin.nil?
52
- map.begin.source.start_with?('<<')
50
+ node.loc.respond_to?(:heredoc_end)
53
51
  end
54
52
 
55
53
  def contain_here_document?(node)
56
- here_document?(node) || node.each_descendent_node.any? { |n| here_document?(n) }
54
+ node.each_node.any? { |n| here_document?(n) }
57
55
  end
58
56
 
59
57
  def in_explicit_parentheses?(node)
@@ -4,8 +4,8 @@ module Transpec
4
4
  # http://semver.org/
5
5
  module Version
6
6
  MAJOR = 1
7
- MINOR = 5
8
- PATCH = 1
7
+ MINOR = 6
8
+ PATCH = 0
9
9
 
10
10
  def self.to_s
11
11
  [MAJOR, MINOR, PATCH].join('.')
@@ -223,8 +223,8 @@ module Transpec
223
223
  end
224
224
 
225
225
  shared_examples 'invokes OnelinerShould#expectize! if available' do
226
- context 'when RSpecVersion#one_liner_is_expected_available? returns true' do
227
- before { rspec_version.stub(:one_liner_is_expected_available?).and_return(true) }
226
+ context 'when RSpecVersion#oneliner_is_expected_available? returns true' do
227
+ before { rspec_version.stub(:oneliner_is_expected_available?).and_return(true) }
228
228
 
229
229
  it 'invokes OnelinerShould#expectize!' do
230
230
  should_object.should_receive(:expectize!)
@@ -232,8 +232,8 @@ module Transpec
232
232
  end
233
233
  end
234
234
 
235
- context 'when RSpecVersion#one_liner_is_expected_available? returns false' do
236
- before { rspec_version.stub(:one_liner_is_expected_available?).and_return(false) }
235
+ context 'when RSpecVersion#oneliner_is_expected_available? returns false' do
236
+ before { rspec_version.stub(:oneliner_is_expected_available?).and_return(false) }
237
237
  include_examples 'does nothing'
238
238
  end
239
239
  end
@@ -655,7 +655,7 @@ module Transpec
655
655
  context 'when Configuration#convert_deprecated_method? is false' do
656
656
  before { configuration.convert_deprecated_method = false }
657
657
 
658
- it 'does not invoke Double#convert_to_double!' do
658
+ it 'does nothing' do
659
659
  double_object.should_not_receive(:convert_to_double!)
660
660
  converter.process_double(double_object)
661
661
  end
@@ -668,7 +668,7 @@ module Transpec
668
668
  context 'when RSpecVersion#be_truthy_available? returns true' do
669
669
  before { rspec_version.stub(:be_truthy_available?).and_return(true) }
670
670
 
671
- context 'when Configuration#convert_deprecated_method? is true' do
671
+ context 'and Configuration#convert_deprecated_method? is true' do
672
672
  before { configuration.convert_deprecated_method = true }
673
673
 
674
674
  context 'and Configuration#boolean_matcher_type is :conditional' do
@@ -703,7 +703,7 @@ module Transpec
703
703
  end
704
704
  end
705
705
 
706
- context 'when Configuration#convert_deprecated_method? is false' do
706
+ context 'and Configuration#convert_deprecated_method? is false' do
707
707
  before { configuration.convert_deprecated_method = false }
708
708
 
709
709
  it 'does nothing' do
@@ -740,7 +740,7 @@ module Transpec
740
740
  context 'when Configuration#convert_deprecated_method? is false' do
741
741
  before { configuration.convert_deprecated_method = false }
742
742
 
743
- it 'does not invoke BeClose#convert_to_be_within!' do
743
+ it 'does nothing' do
744
744
  be_close_object.should_not_receive(:convert_to_be_within!)
745
745
  converter.process_be_close(be_close_object)
746
746
  end
@@ -762,7 +762,7 @@ module Transpec
762
762
  context 'when Configuration#convert_deprecated_method? is false' do
763
763
  before { configuration.convert_deprecated_method = false }
764
764
 
765
- it 'does not invoke BeClose#convert_to_be_within!' do
765
+ it 'does nothing' do
766
766
  raise_error_object.should_not_receive(:remove_error_specification_with_negative_expectation!)
767
767
  converter.process_raise_error(raise_error_object)
768
768
  end
@@ -784,7 +784,7 @@ module Transpec
784
784
  context 'when Configuration#convert_its? is false' do
785
785
  before { configuration.convert_its = false }
786
786
 
787
- it 'does not invoke Its#convert_to_describe_subject_it!' do
787
+ it 'does nothing' do
788
788
  its_object.should_not_receive(:convert_to_describe_subject_it!)
789
789
  converter.process_its(its_object)
790
790
  end
@@ -797,7 +797,7 @@ module Transpec
797
797
  context 'when RSpecVersion#yielded_example_available? returns true' do
798
798
  before { rspec_version.stub(:yielded_example_available?).and_return(true) }
799
799
 
800
- context 'when Configuration#convert_deprecated_method? is true' do
800
+ context 'and Configuration#convert_deprecated_method? is true' do
801
801
  before { configuration.convert_deprecated_method = true }
802
802
 
803
803
  it 'invokes Example#convert!' do
@@ -806,10 +806,10 @@ module Transpec
806
806
  end
807
807
  end
808
808
 
809
- context 'when Configuration#convert_deprecated_method? is false' do
809
+ context 'and Configuration#convert_deprecated_method? is false' do
810
810
  before { configuration.convert_deprecated_method = false }
811
811
 
812
- it 'does not invoke Its#convert_to_describe_subject_it!' do
812
+ it 'does nothing' do
813
813
  example_object.should_not_receive(:convert!)
814
814
  converter.process_example(example_object)
815
815
  end
@@ -819,7 +819,7 @@ module Transpec
819
819
  context 'when RSpecVersion#yielded_example_available? returns false' do
820
820
  before { rspec_version.stub(:yielded_example_available?).and_return(false) }
821
821
 
822
- context 'when Configuration#convert_deprecated_method? is true' do
822
+ context 'and Configuration#convert_deprecated_method? is true' do
823
823
  before { configuration.convert_deprecated_method = true }
824
824
 
825
825
  it 'does nothing' do
@@ -830,6 +830,45 @@ module Transpec
830
830
  end
831
831
  end
832
832
 
833
+ describe '#process_matcher_definition' do
834
+ let(:matcher_definition) { double('matcher_definition').as_null_object }
835
+
836
+ context 'when RSpecVersion#non_should_matcher_protocol_available? returns true' do
837
+ before { rspec_version.stub(:non_should_matcher_protocol_available?).and_return(true) }
838
+
839
+ context 'and Configuration#convert_deprecated_method? is true' do
840
+ before { configuration.convert_deprecated_method = true }
841
+
842
+ it 'invokes MatcherDefinition#convert_deprecated_method!' do
843
+ matcher_definition.should_receive(:convert_deprecated_method!)
844
+ converter.process_matcher_definition(matcher_definition)
845
+ end
846
+ end
847
+
848
+ context 'and Configuration#convert_deprecated_method? is false' do
849
+ before { configuration.convert_deprecated_method = false }
850
+
851
+ it 'does nothing' do
852
+ matcher_definition.should_not_receive(:convert_deprecated_method!)
853
+ converter.process_matcher_definition(matcher_definition)
854
+ end
855
+ end
856
+ end
857
+
858
+ context 'when RSpecVersion#non_should_matcher_protocol_available? returns false' do
859
+ before { rspec_version.stub(:non_should_matcher_protocol_available?).and_return(false) }
860
+
861
+ context 'and Configuration#convert_deprecated_method? is true' do
862
+ before { configuration.convert_deprecated_method = true }
863
+
864
+ it 'does nothing' do
865
+ matcher_definition.should_not_receive(:convert_deprecated_method!)
866
+ converter.process_matcher_definition(matcher_definition)
867
+ end
868
+ end
869
+ end
870
+ end
871
+
833
872
  describe '#process_rspec_configure' do
834
873
  let(:rspec_configure) { double('rspec_configure').as_null_object }
835
874
 
@@ -15,10 +15,8 @@ module Transpec
15
15
 
16
16
  let(:source) do
17
17
  <<-END
18
- describe 'example' do
19
- it 'is foo' do
20
- subject.should be(foo)
21
- end
18
+ it 'is foo' do
19
+ subject.should be(foo)
22
20
  end
23
21
  END
24
22
  end
@@ -26,10 +24,8 @@ module Transpec
26
24
  # rubocop:disable LineLength
27
25
  let(:expected_source) do
28
26
  <<-END
29
- describe 'example' do
30
- it 'is foo' do
31
- transpec_analysis((transpec_analysis((subject), self, { :should_source_location => [:object, "method(:should).source_location"] }, __FILE__, 79, 86).should be(foo)), self, { :expect_available? => [:context, "self.class.ancestors.any? { |a| a.name.start_with?('RSpec::') } && respond_to?(:expect)"] }, __FILE__, 79, 101)
32
- end
27
+ it 'is foo' do
28
+ transpec_analysis((transpec_analysis((subject), self, { :should_source_location => [:object, "method(:should).source_location"] }, __FILE__, 41, 48).should be(foo)), self, { :expect_available? => [:context, "self.class.ancestors.any? { |a| a.name.start_with?('RSpec::') } && respond_to?(:expect)"] }, __FILE__, 41, 63)
33
29
  end
34
30
  END
35
31
  end
@@ -42,12 +38,10 @@ module Transpec
42
38
  context 'when the target includes here document' do
43
39
  let(:source) do
44
40
  <<-END
45
- describe 'example' do
46
- it 'matches to foo' do
47
- subject.should =~ <<-HEREDOC.gsub('foo', 'bar')
48
- foo
49
- HEREDOC
50
- end
41
+ it 'matches to foo' do
42
+ subject.should =~ <<-HEREDOC.gsub('foo', 'bar')
43
+ foo
44
+ HEREDOC
51
45
  end
52
46
  END
53
47
  end
@@ -55,13 +49,10 @@ module Transpec
55
49
  # rubocop:disable LineLength
56
50
  let(:expected_source) do
57
51
  <<-END
58
- describe 'example' do
59
- it 'matches to foo' do
60
- transpec_analysis((transpec_analysis((subject), self, { :should_source_location => [:object, "method(:should).source_location"] }, __FILE__, 93, 100).should), self, { :"=~_source_location" => [:object, "method(:=~).source_location"], :expect_available? => [:context, "self.class.ancestors.any? { |a| a.name.start_with?('RSpec::') } && respond_to?(:expect)"] }, __FILE__, 93, 107) =~ transpec_analysis((<<-HEREDOC.gsub('foo', 'bar')
61
- foo
62
- HEREDOC
63
- ), self, { :arg_is_enumerable? => [:object, "is_a?(Enumerable)"] }, __FILE__, 111, 188)
64
- end
52
+ it 'matches to foo' do
53
+ transpec_analysis((transpec_analysis((subject), self, { :should_source_location => [:object, "method(:should).source_location"] }, __FILE__, 53, 60).should), self, { :"=~_source_location" => [:object, "method(:=~).source_location"], :expect_available? => [:context, "self.class.ancestors.any? { |a| a.name.start_with?('RSpec::') } && respond_to?(:expect)"] }, __FILE__, 53, 67) =~ transpec_analysis((<<-HEREDOC.gsub('foo', 'bar')), self, { :arg_is_enumerable? => [:object, "is_a?(Enumerable)"] }, __FILE__, 71, 100)
54
+ foo
55
+ HEREDOC
65
56
  end
66
57
  END
67
58
  end
@@ -75,10 +66,8 @@ module Transpec
75
66
  context 'when the target takes block' do
76
67
  let(:source) do
77
68
  <<-END
78
- describe 'example' do
79
- it 'raises error' do
80
- expect { do_something }.to throw_symbol
81
- end
69
+ it 'raises error' do
70
+ expect { do_something }.to throw_symbol
82
71
  end
83
72
  END
84
73
  end
@@ -86,10 +75,8 @@ module Transpec
86
75
  # rubocop:disable LineLength
87
76
  let(:expected_source) do
88
77
  <<-END
89
- describe 'example' do
90
- it 'raises error' do
91
- transpec_analysis((expect { do_something }), self, { :expect_source_location => [:context, "method(:expect).source_location"] }, __FILE__, 91, 97).to throw_symbol
92
- end
78
+ it 'raises error' do
79
+ transpec_analysis((expect { do_something }), self, { :expect_source_location => [:context, "method(:expect).source_location"] }, __FILE__, 51, 57).to throw_symbol
93
80
  end
94
81
  END
95
82
  end
@@ -103,10 +90,8 @@ module Transpec
103
90
  context 'when the target is only the expression in a block' do
104
91
  let(:source) do
105
92
  <<-END
106
- describe 'example' do
107
- it 'raises error' do
108
- expect
109
- end
93
+ it 'raises error' do
94
+ expect
110
95
  end
111
96
  END
112
97
  end
@@ -114,10 +99,8 @@ module Transpec
114
99
  # rubocop:disable LineLength
115
100
  let(:expected_source) do
116
101
  <<-END
117
- describe 'example' do
118
- it 'raises error' do
119
- transpec_analysis((expect), self, { :expect_source_location => [:context, "method(:expect).source_location"] }, __FILE__, 91, 97)
120
- end
102
+ it 'raises error' do
103
+ transpec_analysis((expect), self, { :expect_source_location => [:context, "method(:expect).source_location"] }, __FILE__, 51, 57)
121
104
  end
122
105
  END
123
106
  end
@@ -131,10 +114,8 @@ module Transpec
131
114
  context 'when the target is method invocation without parentheses' do
132
115
  let(:source) do
133
116
  <<-END
134
- describe 'example' do
135
- it 'raises error' do
136
- expect subject
137
- end
117
+ it 'raises error' do
118
+ expect subject
138
119
  end
139
120
  END
140
121
  end
@@ -142,10 +123,8 @@ module Transpec
142
123
  # rubocop:disable LineLength
143
124
  let(:expected_source) do
144
125
  <<-END
145
- describe 'example' do
146
- it 'raises error' do
147
- transpec_analysis((expect subject), self, { :expect_source_location => [:context, "method(:expect).source_location"] }, __FILE__, 91, 105)
148
- end
126
+ it 'raises error' do
127
+ transpec_analysis((expect subject), self, { :expect_source_location => [:context, "method(:expect).source_location"] }, __FILE__, 51, 65)
149
128
  end
150
129
  END
151
130
  end