transpec 1.5.1 → 1.6.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.
@@ -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