transpec 1.8.0 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,16 +8,22 @@ require 'ast'
8
8
  module Transpec
9
9
  class Syntax
10
10
  class OperatorMatcher < Syntax
11
- include Mixin::Send, Util, ::AST::Sexp
11
+ extend ::AST::Sexp
12
+ include Mixin::Send, Util
12
13
 
13
14
  OPERATORS = [:==, :===, :<, :<=, :>, :>=, :=~].freeze
15
+ BE_NODE = s(:send, nil, :be)
14
16
 
15
17
  def self.standalone?
16
18
  false
17
19
  end
18
20
 
19
- def self.target_method?(receiver_node, method_name)
20
- !receiver_node.nil? && OPERATORS.include?(method_name)
21
+ def self.target_node?(node, runtime_data = nil)
22
+ node = node.parent_node if node == BE_NODE
23
+ receiver_node, method_name, *_ = *node
24
+ return false if receiver_node.nil?
25
+ return false unless OPERATORS.include?(method_name)
26
+ check_target_node_dynamically(node, runtime_data)
21
27
  end
22
28
 
23
29
  add_dynamic_analysis_request do |rewriter|
@@ -26,6 +32,16 @@ module Transpec
26
32
  end
27
33
  end
28
34
 
35
+ def initialize(node, source_rewriter = nil, runtime_data = nil, report = nil)
36
+ operator_node = if node == BE_NODE
37
+ node.parent_node
38
+ else
39
+ node
40
+ end
41
+
42
+ super(operator_node, source_rewriter, runtime_data, report)
43
+ end
44
+
29
45
  def convert_operator!(parenthesize_arg = true)
30
46
  case method_name
31
47
  when :==
@@ -126,7 +142,7 @@ module Transpec
126
142
  end
127
143
 
128
144
  def be_node
129
- if receiver_node == s(:send, nil, :be)
145
+ if receiver_node == BE_NODE
130
146
  receiver_node
131
147
  else
132
148
  nil
@@ -3,12 +3,12 @@
3
3
  require 'transpec/syntax'
4
4
  require 'transpec/syntax/mixin/send'
5
5
  require 'transpec/syntax/mixin/owned_matcher'
6
- require 'transpec/syntax/mixin/any_instance_block'
6
+ require 'transpec/syntax/mixin/messaging_host'
7
7
 
8
8
  module Transpec
9
9
  class Syntax
10
10
  class Receive < Syntax
11
- include Mixin::Send, Mixin::OwnedMatcher, Mixin::AnyInstanceBlock
11
+ include Mixin::Send, Mixin::OwnedMatcher, Mixin::MessagingHost
12
12
 
13
13
  attr_reader :expectation
14
14
 
@@ -16,13 +16,16 @@ module Transpec
16
16
  receiver_node.nil? && method_name == :receive
17
17
  end
18
18
 
19
+ def remove_useless_and_return!
20
+ removed = super
21
+ return unless removed
22
+ @report.records << ReceiveUselessAndReturnRecord.new(self)
23
+ end
24
+
19
25
  def add_receiver_arg_to_any_instance_implementation_block!
20
26
  added = super
21
27
  return unless added
22
- @report.records << Record.new(
23
- "#{@expectation.method_name}(Klass).to receive(:message) { |arg| }",
24
- "#{@expectation.method_name}(Klass).to receive(:message) { |instance, arg| }"
25
- )
28
+ @report.records << ReceiveAnyInstanceBlockRecord.new(self)
26
29
  end
27
30
 
28
31
  def any_instance?
@@ -33,6 +36,18 @@ module Transpec
33
36
  return unless any_instance?
34
37
  super || @expectation.block_node
35
38
  end
39
+
40
+ class ReceiveAnyInstanceBlockRecord < AnyInstanceBlockRecord
41
+ def base_syntax
42
+ "#{@host.expectation.method_name}(Klass).to receive(:message)"
43
+ end
44
+ end
45
+
46
+ class ReceiveUselessAndReturnRecord < UselessAndReturnRecord
47
+ def base_syntax
48
+ "#{@host.expectation.method_name_for_instance}(obj).to receive(:message)"
49
+ end
50
+ end
36
51
  end
37
52
  end
38
53
  end
@@ -3,14 +3,13 @@
3
3
  require 'transpec/syntax'
4
4
  require 'transpec/syntax/mixin/expectizable'
5
5
  require 'transpec/syntax/mixin/monkey_patch_any_instance'
6
- require 'transpec/syntax/mixin/allow_no_message'
7
- require 'transpec/syntax/mixin/any_instance_block'
6
+ require 'transpec/syntax/mixin/messaging_host'
7
+ require 'transpec/util'
8
8
 
9
9
  module Transpec
10
10
  class Syntax
11
11
  class ShouldReceive < Syntax
12
- include Mixin::Expectizable, Mixin::MonkeyPatchAnyInstance, Mixin::AnyInstanceBlock,
13
- Mixin::AllowNoMessage
12
+ include Mixin::Expectizable, Mixin::MonkeyPatchAnyInstance, Mixin::MessagingHost, Util
14
13
 
15
14
  alias_method :useless_expectation?, :allow_no_message?
16
15
 
@@ -61,7 +60,7 @@ module Transpec
61
60
  end
62
61
 
63
62
  convert_to_syntax!('allow', negative_form)
64
- remove_allowance_for_no_message!
63
+ remove_no_message_allowance!
65
64
 
66
65
  register_record(AllowRecord, negative_form)
67
66
  end
@@ -70,13 +69,17 @@ module Transpec
70
69
  return unless useless_expectation?
71
70
 
72
71
  replace(selector_range, 'stub')
73
- remove_allowance_for_no_message!
72
+ remove_no_message_allowance!
74
73
 
75
74
  register_record(StubRecord)
76
75
  end
77
76
 
77
+ def remove_useless_and_return!
78
+ super && register_record(MonkeyPatchUselessAndReturnRecord)
79
+ end
80
+
78
81
  def add_receiver_arg_to_any_instance_implementation_block!
79
- super && register_record(AnyInstanceBlockRecord)
82
+ super && register_record(MonkeyPatchAnyInstanceBlockRecord)
80
83
  end
81
84
 
82
85
  private
@@ -112,7 +115,7 @@ module Transpec
112
115
  def broken_block_nodes
113
116
  @broken_block_nodes ||= [
114
117
  block_node_taken_by_with_method_with_no_normal_args,
115
- block_node_following_message_expectation_method
118
+ block_node_followed_by_fluent_method
116
119
  ].compact.uniq
117
120
  end
118
121
 
@@ -128,7 +131,7 @@ module Transpec
128
131
  # (args
129
132
  # (arg :block_arg)) nil)
130
133
  def block_node_taken_by_with_method_with_no_normal_args
131
- each_chained_method_node do |chained_node, child_node|
134
+ each_backward_chained_node(node, :child_as_second_arg) do |chained_node, child_node|
132
135
  next unless chained_node.block_type?
133
136
  return nil unless child_node.children[1] == :with
134
137
  return nil if child_node.children[2]
@@ -146,8 +149,8 @@ module Transpec
146
149
  # (sym :method_name))
147
150
  # (args
148
151
  # (arg :block_arg)) nil) :once)
149
- def block_node_following_message_expectation_method
150
- each_chained_method_node do |chained_node, child_node|
152
+ def block_node_followed_by_fluent_method
153
+ each_backward_chained_node(node, :child_as_second_arg) do |chained_node, child_node|
151
154
  next unless chained_node.send_type?
152
155
  return child_node if child_node.block_type?
153
156
  end
@@ -74,6 +74,52 @@ module Transpec
74
74
  parent_node
75
75
  end
76
76
 
77
+ def each_forward_chained_node(origin_node, mode = nil)
78
+ return to_enum(__method__, origin_node, mode) unless block_given?
79
+
80
+ yield origin_node if mode == :include_origin
81
+
82
+ parent_node = origin_node
83
+
84
+ loop do
85
+ child_node = parent_node.children.first
86
+
87
+ return unless child_node
88
+ return unless [:send, :block].include?(child_node.type)
89
+
90
+ if mode == :parent_as_second_arg
91
+ yield child_node, parent_node
92
+ else
93
+ yield child_node
94
+ end
95
+
96
+ parent_node = child_node
97
+ end
98
+
99
+ nil
100
+ end
101
+
102
+ def each_backward_chained_node(origin_node, mode = nil)
103
+ return to_enum(__method__, origin_node, mode) unless block_given?
104
+
105
+ yield origin_node if mode == :include_origin
106
+
107
+ origin_node.each_ancestor_node.reduce(origin_node) do |child_node, parent_node|
108
+ return unless [:send, :block].include?(parent_node.type)
109
+ return unless parent_node.children.first.equal?(child_node)
110
+
111
+ if mode == :child_as_second_arg
112
+ yield parent_node, child_node
113
+ else
114
+ yield parent_node
115
+ end
116
+
117
+ parent_node
118
+ end
119
+
120
+ nil
121
+ end
122
+
77
123
  def indentation_of_line(arg)
78
124
  line = case arg
79
125
  when AST::Node then arg.loc.expression.source_line
@@ -4,7 +4,7 @@ module Transpec
4
4
  # http://semver.org/
5
5
  module Version
6
6
  MAJOR = 1
7
- MINOR = 8
7
+ MINOR = 9
8
8
  PATCH = 0
9
9
 
10
10
  def self.to_s
@@ -367,7 +367,7 @@ module Transpec
367
367
 
368
368
  describe '#process_expect' do
369
369
  let(:expect_object) { double('expect_object', receive_matcher: receive_object).as_null_object }
370
- let(:receive_object) { double('receive_object') }
370
+ let(:receive_object) { double('receive_object').as_null_object }
371
371
 
372
372
  context 'when Configuration#convert_have_items? is true' do
373
373
  before { configuration.convert_have_items = true }
@@ -400,6 +400,11 @@ module Transpec
400
400
  end
401
401
  end
402
402
 
403
+ it "invokes #process_useless_and_return with the expect's #receive matcher" do
404
+ converter.should_receive(:process_useless_and_return).with(receive_object)
405
+ converter.process_expect(expect_object)
406
+ end
407
+
403
408
  it "invokes #process_any_instance_block with the expect's #receive matcher" do
404
409
  converter.should_receive(:process_any_instance_block).with(receive_object)
405
410
  converter.process_expect(expect_object)
@@ -408,7 +413,12 @@ module Transpec
408
413
 
409
414
  describe '#process_allow' do
410
415
  let(:allow_object) { double('allow_object', receive_matcher: receive_object).as_null_object }
411
- let(:receive_object) { double('receive_object') }
416
+ let(:receive_object) { double('receive_object').as_null_object }
417
+
418
+ it "invokes #process_useless_and_return with the allow's #receive matcher" do
419
+ converter.should_receive(:process_useless_and_return).with(receive_object)
420
+ converter.process_allow(allow_object)
421
+ end
412
422
 
413
423
  it "invokes #process_any_instance_block with the allow's #receive matcher" do
414
424
  converter.should_receive(:process_any_instance_block).with(receive_object)
@@ -573,9 +583,14 @@ module Transpec
573
583
  end
574
584
  end
575
585
 
586
+ it 'invokes #process_useless_and_return with the should_receive' do
587
+ converter.should_receive(:process_useless_and_return).with(should_receive_object)
588
+ converter.process_should_receive(should_receive_object)
589
+ end
590
+
576
591
  it 'invokes #process_any_instance_block with the should_receive' do
577
592
  converter.should_receive(:process_any_instance_block).with(should_receive_object)
578
- converter.process_allow(should_receive_object)
593
+ converter.process_should_receive(should_receive_object)
579
594
  end
580
595
  end
581
596
 
@@ -610,16 +625,16 @@ module Transpec
610
625
  end
611
626
  end
612
627
 
613
- shared_examples 'invokes MethodStub#remove_allowance_for_no_message!' do
614
- it 'invokes MethodStub#remove_allowance_for_no_message!' do
615
- method_stub_object.should_receive(:remove_allowance_for_no_message!)
628
+ shared_examples 'invokes MethodStub#remove_no_message_allowance!' do
629
+ it 'invokes MethodStub#remove_no_message_allowance!' do
630
+ method_stub_object.should_receive(:remove_no_message_allowance!)
616
631
  converter.process_method_stub(method_stub_object)
617
632
  end
618
633
  end
619
634
 
620
- shared_examples 'does not invoke MethodStub#remove_allowance_for_no_message!' do
621
- it 'does not invoke MethodStub#remove_allowance_for_no_message!' do
622
- method_stub_object.should_not_receive(:remove_allowance_for_no_message!)
635
+ shared_examples 'does not invoke MethodStub#remove_no_message_allowance!' do
636
+ it 'does not invoke MethodStub#remove_no_message_allowance!' do
637
+ method_stub_object.should_not_receive(:remove_no_message_allowance!)
623
638
  converter.process_method_stub(method_stub_object)
624
639
  end
625
640
  end
@@ -634,7 +649,7 @@ module Transpec
634
649
  before { method_stub_object.stub(:hash_arg?).and_return(false) }
635
650
  include_examples 'invokes MethodStub#allowize!'
636
651
  include_examples 'does not invoke MethodStub#convert_deprecated_method!'
637
- include_examples 'invokes MethodStub#remove_allowance_for_no_message!'
652
+ include_examples 'invokes MethodStub#remove_no_message_allowance!'
638
653
  end
639
654
 
640
655
  context 'and MethodStub#hash_arg? is true' do
@@ -647,14 +662,14 @@ module Transpec
647
662
  before { rspec_version.stub(:receive_messages_available?).and_return(true) }
648
663
  include_examples 'invokes MethodStub#allowize!'
649
664
  include_examples 'does not invoke MethodStub#convert_deprecated_method!'
650
- include_examples 'invokes MethodStub#remove_allowance_for_no_message!'
665
+ include_examples 'invokes MethodStub#remove_no_message_allowance!'
651
666
  end
652
667
 
653
668
  context 'and RSpecVersion#receive_messages_available? is false' do
654
669
  before { rspec_version.stub(:receive_messages_available?).and_return(false) }
655
670
  include_examples 'invokes MethodStub#allowize!'
656
671
  include_examples 'does not invoke MethodStub#convert_deprecated_method!'
657
- include_examples 'invokes MethodStub#remove_allowance_for_no_message!'
672
+ include_examples 'invokes MethodStub#remove_no_message_allowance!'
658
673
  end
659
674
  end
660
675
 
@@ -665,14 +680,14 @@ module Transpec
665
680
  before { rspec_version.stub(:receive_messages_available?).and_return(true) }
666
681
  include_examples 'invokes MethodStub#allowize!'
667
682
  include_examples 'does not invoke MethodStub#convert_deprecated_method!'
668
- include_examples 'invokes MethodStub#remove_allowance_for_no_message!'
683
+ include_examples 'invokes MethodStub#remove_no_message_allowance!'
669
684
  end
670
685
 
671
686
  context 'and RSpecVersion#receive_messages_available? is false' do
672
687
  before { rspec_version.stub(:receive_messages_available?).and_return(false) }
673
688
  include_examples 'does not invoke MethodStub#allowize!'
674
689
  include_examples 'invokes MethodStub#convert_deprecated_method!'
675
- include_examples 'invokes MethodStub#remove_allowance_for_no_message!'
690
+ include_examples 'invokes MethodStub#remove_no_message_allowance!'
676
691
  end
677
692
  end
678
693
  end
@@ -686,7 +701,7 @@ module Transpec
686
701
 
687
702
  include_examples 'invokes MethodStub#allowize!'
688
703
  include_examples 'does not invoke MethodStub#convert_deprecated_method!'
689
- include_examples 'does not invoke MethodStub#remove_allowance_for_no_message!'
704
+ include_examples 'does not invoke MethodStub#remove_no_message_allowance!'
690
705
  end
691
706
  end
692
707
 
@@ -698,7 +713,7 @@ module Transpec
698
713
 
699
714
  include_examples 'does not invoke MethodStub#allowize!'
700
715
  include_examples 'invokes MethodStub#convert_deprecated_method!'
701
- include_examples 'invokes MethodStub#remove_allowance_for_no_message!'
716
+ include_examples 'invokes MethodStub#remove_no_message_allowance!'
702
717
  end
703
718
 
704
719
  context 'and Configuration#convert_deprecated_method? is false' do
@@ -706,13 +721,18 @@ module Transpec
706
721
 
707
722
  include_examples 'does not invoke MethodStub#allowize!'
708
723
  include_examples 'does not invoke MethodStub#convert_deprecated_method!'
709
- include_examples 'does not invoke MethodStub#remove_allowance_for_no_message!'
724
+ include_examples 'does not invoke MethodStub#remove_no_message_allowance!'
710
725
  end
711
726
  end
712
727
 
728
+ it 'invokes #process_useless_and_return with the method stub' do
729
+ converter.should_receive(:process_useless_and_return).with(method_stub_object)
730
+ converter.process_method_stub(method_stub_object)
731
+ end
732
+
713
733
  it 'invokes #process_any_instance_block with the method stub' do
714
734
  converter.should_receive(:process_any_instance_block).with(method_stub_object)
715
- converter.process_allow(method_stub_object)
735
+ converter.process_method_stub(method_stub_object)
716
736
  end
717
737
  end
718
738
 
@@ -1047,6 +1067,28 @@ module Transpec
1047
1067
  end
1048
1068
  end
1049
1069
 
1070
+ describe '#process_useless_and_return' do
1071
+ let(:messaging_host) { double('messaging host').as_null_object }
1072
+
1073
+ context 'when Configuration#convert_deprecated_method? returns true' do
1074
+ before { configuration.convert_deprecated_method = true }
1075
+
1076
+ it 'invokes #remove_useless_and_return!' do
1077
+ messaging_host.should_receive(:remove_useless_and_return!)
1078
+ converter.process_useless_and_return(messaging_host)
1079
+ end
1080
+ end
1081
+
1082
+ context 'when Configuration#convert_deprecated_method? returns false' do
1083
+ before { configuration.convert_deprecated_method = false }
1084
+
1085
+ it 'does nothing' do
1086
+ messaging_host.should_not_receive(:remove_useless_and_return!)
1087
+ converter.process_useless_and_return(messaging_host)
1088
+ end
1089
+ end
1090
+ end
1091
+
1050
1092
  describe '#process_any_instance_block' do
1051
1093
  let(:messaging_host) { double('messaging host').as_null_object }
1052
1094
 
@@ -27,37 +27,69 @@ module Transpec
27
27
  end
28
28
 
29
29
  describe '#matcher_node' do
30
- context 'when the matcher is taking a block' do
30
+ let(:matcher_name) { expect_object.matcher_node.children[1] }
31
+
32
+ context 'when the matcher is not taking a block' do
31
33
  let(:source) do
32
34
  <<-END
33
35
  describe 'example' do
34
36
  it 'is empty' do
35
- expect(subject).to receive(:foo) { }
37
+ expect(subject).to be_empty
36
38
  end
37
39
  end
38
40
  END
39
41
  end
40
42
 
41
43
  it 'returns send node of the matcher' do
42
- method_name = expect_object.matcher_node.children[1]
43
- method_name.should == :receive
44
+ matcher_name.should == :be_empty
44
45
  end
45
46
  end
46
47
 
47
- context 'when the matcher is not taking a block' do
48
+ context 'when the matcher is taking a block' do
48
49
  let(:source) do
49
50
  <<-END
50
51
  describe 'example' do
51
- it 'is empty' do
52
- expect(subject).to be_empty
52
+ it 'receives :foo' do
53
+ expect(subject).to receive(:foo) { }
53
54
  end
54
55
  end
55
56
  END
56
57
  end
57
58
 
58
59
  it 'returns send node of the matcher' do
59
- method_name = expect_object.matcher_node.children[1]
60
- method_name.should == :be_empty
60
+ matcher_name.should == :receive
61
+ end
62
+ end
63
+
64
+ context 'when the matcher is chained by another method' do
65
+ let(:source) do
66
+ <<-END
67
+ describe 'example' do
68
+ it 'receives :foo twice' do
69
+ expect(subject).to receive(:foo).twice
70
+ end
71
+ end
72
+ END
73
+ end
74
+
75
+ it 'returns the first node of the chain' do
76
+ matcher_name.should == :receive
77
+ end
78
+ end
79
+
80
+ context 'when the matcher is chained by another method that is taking a block' do
81
+ let(:source) do
82
+ <<-END
83
+ describe 'example' do
84
+ it 'receives :foo twice' do
85
+ expect(subject).to receive(:foo).twice { }
86
+ end
87
+ end
88
+ END
89
+ end
90
+
91
+ it 'returns the first node of the chain' do
92
+ matcher_name.should == :receive
61
93
  end
62
94
  end
63
95
  end