transpec 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,17 +4,56 @@ module Transpec
4
4
  class Syntax
5
5
  module Mixin
6
6
  module AnyInstance
7
+ include ::AST::Sexp
8
+
9
+ def register_request_of_any_instance_inspection(rewriter)
10
+ key = :any_instance_target_class_name
11
+ code = <<-END.gsub(/^\s+\|/, '').chomp
12
+ |if self.class.name == 'RSpec::Mocks::AnyInstance::Recorder'
13
+ | if respond_to?(:klass)
14
+ | klass.name
15
+ | elsif instance_variable_defined?(:@klass)
16
+ | instance_variable_get(:@klass).name
17
+ | else
18
+ | nil
19
+ | end
20
+ |else
21
+ | nil
22
+ |end
23
+ END
24
+ rewriter.register_request(subject_node, key, code)
25
+ end
26
+
7
27
  def any_instance?
8
- !class_node_of_any_instance.nil?
28
+ return true unless any_instance_target_node.nil?
29
+ node_data = runtime_node_data(subject_node)
30
+ return false unless node_data
31
+ return false unless node_data[:any_instance_target_class_name]
32
+ !node_data[:any_instance_target_class_name].result.nil?
9
33
  end
10
34
 
11
- def class_node_of_any_instance
35
+ def any_instance_target_class_source
36
+ return nil unless any_instance?
37
+
38
+ if any_instance_target_node
39
+ any_instance_target_node.loc.expression.source
40
+ else
41
+ runtime_node_data(subject_node)[:any_instance_target_class_name].result
42
+ end
43
+ end
44
+
45
+ def any_instance_target_node
12
46
  return nil unless subject_node.type == :send
13
47
  return nil unless subject_node.children.count == 2
14
48
  receiver_node, method_name = *subject_node
49
+ return nil unless receiver_node
15
50
  return nil unless method_name == :any_instance
16
- return nil unless receiver_node.type == :const
17
- receiver_node
51
+
52
+ if receiver_node.type == :const || receiver_node == s(:send, nil, :described_class)
53
+ receiver_node
54
+ else
55
+ nil
56
+ end
18
57
  end
19
58
  end
20
59
  end
@@ -88,6 +88,10 @@ module Transpec
88
88
  arg_node.loc.expression
89
89
  end
90
90
 
91
+ def args_range
92
+ arg_nodes.first.loc.expression.begin.join(arg_nodes.last.loc.expression.end)
93
+ end
94
+
91
95
  def parentheses_range
92
96
  selector_range.end.join(expression_range.end)
93
97
  end
@@ -34,6 +34,8 @@ module Transpec
34
34
  :allow_to_receive_available?,
35
35
  [:allow, :receive]
36
36
  )
37
+
38
+ register_request_of_any_instance_inspection(rewriter)
37
39
  end
38
40
 
39
41
  def expect_to_receive_available?
@@ -83,7 +85,7 @@ module Transpec
83
85
 
84
86
  def convert_to_syntax!(syntax, negative_form)
85
87
  if any_instance?
86
- wrap_class_with_any_instance_of!(syntax)
88
+ wrap_subject_with_any_instance_of!(syntax)
87
89
  else
88
90
  wrap_subject_with_method!(syntax)
89
91
  end
@@ -104,11 +106,9 @@ module Transpec
104
106
  end
105
107
  end
106
108
 
107
- def wrap_class_with_any_instance_of!(syntax)
108
- insert_before(subject_range, "#{syntax}_any_instance_of(")
109
- map = subject_node.loc
110
- dot_any_instance_range = map.dot.join(map.selector)
111
- replace(dot_any_instance_range, ')')
109
+ def wrap_subject_with_any_instance_of!(syntax)
110
+ expression = "#{syntax}_any_instance_of(#{any_instance_target_class_source})"
111
+ replace(subject_range, expression)
112
112
  end
113
113
 
114
114
  def broken_block_nodes
@@ -164,7 +164,7 @@ module Transpec
164
164
 
165
165
  def original_syntax(conversion_type)
166
166
  syntax = if any_instance? && conversion_type != :stub
167
- 'SomeClass.any_instance.'
167
+ 'Klass.any_instance.'
168
168
  else
169
169
  'obj.'
170
170
  end
@@ -186,13 +186,13 @@ module Transpec
186
186
  syntax = case conversion_type
187
187
  when :expect
188
188
  if any_instance?
189
- 'expect_any_instance_of(SomeClass).'
189
+ 'expect_any_instance_of(Klass).'
190
190
  else
191
191
  'expect(obj).'
192
192
  end
193
193
  when :allow
194
194
  if any_instance?
195
- 'allow_any_instance_of(SomeClass).'
195
+ 'allow_any_instance_of(Klass).'
196
196
  else
197
197
  'allow(obj).'
198
198
  end
@@ -4,8 +4,8 @@ module Transpec
4
4
  # http://semver.org/
5
5
  module Version
6
6
  MAJOR = 1
7
- MINOR = 2
8
- PATCH = 2
7
+ MINOR = 3
8
+ PATCH = 0
9
9
 
10
10
  def self.to_s
11
11
  [MAJOR, MINOR, PATCH].join('.')
@@ -224,14 +224,14 @@ module Transpec
224
224
  let(:source) do
225
225
  <<-END
226
226
  describe 'example group' do
227
- class SomeClass
227
+ class Klass
228
228
  def some_method
229
229
  1.should == 1
230
230
  end
231
231
  end
232
232
 
233
233
  it 'is an example' do
234
- SomeClass.new.some_method
234
+ Klass.new.some_method
235
235
  end
236
236
  end
237
237
  END
@@ -97,14 +97,14 @@ module Transpec
97
97
  let(:source) do
98
98
  <<-END
99
99
  describe 'example group' do
100
- class SomeClass
100
+ class Klass
101
101
  def some_method
102
102
  1.should == 1
103
103
  end
104
104
  end
105
105
 
106
106
  it 'is an example' do
107
- SomeClass.new.some_method
107
+ Klass.new.some_method
108
108
  end
109
109
  end
110
110
  END
@@ -481,7 +481,7 @@ module Transpec
481
481
  <<-END
482
482
  describe 'foo' do
483
483
  it 'is an example' do
484
- class SomeClass
484
+ class Klass
485
485
  target
486
486
  end
487
487
  end
@@ -497,13 +497,13 @@ module Transpec
497
497
  <<-END
498
498
  describe 'foo' do
499
499
  it 'is an example' do
500
- class SomeClass
500
+ class Klass
501
501
  def some_method
502
502
  target
503
503
  end
504
504
  end
505
505
 
506
- SomeClass.new.some_method
506
+ Klass.new.some_method
507
507
  end
508
508
  end
509
509
  END
@@ -583,14 +583,14 @@ module Transpec
583
583
  context 'when in an instance method in a class' do
584
584
  let(:source) do
585
585
  <<-END
586
- class SomeClass
586
+ class Klass
587
587
  def some_method
588
588
  target
589
589
  end
590
590
  end
591
591
 
592
592
  describe 'test' do
593
- example { SomeClass.new.some_method }
593
+ example { Klass.new.some_method }
594
594
  end
595
595
  END
596
596
  end
@@ -70,6 +70,58 @@ module Transpec
70
70
  describe '#convert_to_standard_expectation!' do
71
71
  let(:record) { have_object.report.records.last }
72
72
 
73
+ context 'when rspec-rails is loaded in the spec' do
74
+ include_context 'dynamic analysis objects'
75
+
76
+ let(:source) do
77
+ <<-END
78
+ module RSpec
79
+ module Rails
80
+ end
81
+ end
82
+
83
+ describe 'example' do
84
+ it 'has 2 items' do
85
+ [:foo, :bar].should have(2).items
86
+ end
87
+ end
88
+ END
89
+ end
90
+
91
+ let(:have_object) { should_object.have_matcher }
92
+
93
+ it 'does nothing' do
94
+ have_object.convert_to_standard_expectation!
95
+ rewritten_source.should == source
96
+ end
97
+ end
98
+
99
+ context 'when rspec-collection_matchers is loaded in the spec' do
100
+ include_context 'dynamic analysis objects'
101
+
102
+ let(:source) do
103
+ <<-END
104
+ module RSpec
105
+ module CollectionMatchers
106
+ end
107
+ end
108
+
109
+ describe 'example' do
110
+ it 'has 2 items' do
111
+ [:foo, :bar].should have(2).items
112
+ end
113
+ end
114
+ END
115
+ end
116
+
117
+ let(:have_object) { should_object.have_matcher }
118
+
119
+ it 'does nothing' do
120
+ have_object.convert_to_standard_expectation!
121
+ rewritten_source.should == source
122
+ end
123
+ end
124
+
73
125
  context 'when it is `collection.should have(2).items` form' do
74
126
  let(:source) do
75
127
  <<-END
@@ -618,6 +670,309 @@ module Transpec
618
670
  end
619
671
  end
620
672
  end
673
+
674
+ context 'when it is `expect(subject).to have(1).word` form' do
675
+ let(:have_object) { expect_object.have_matcher }
676
+
677
+ context 'with runtime information' do
678
+ include_context 'dynamic analysis objects'
679
+
680
+ context 'when the subject responds to #words and #words responds to #size' do
681
+ context 'and ActiveSupport::Inflector.pluralize is available in the spec' do
682
+ let(:source) do
683
+ <<-END
684
+ require 'active_support/inflector'
685
+
686
+ class String
687
+ def words
688
+ split(' ')
689
+ end
690
+ end
691
+
692
+ describe 'string' do
693
+ it 'has a word' do
694
+ expect(subject).to have(1).word
695
+ end
696
+ end
697
+ END
698
+ end
699
+
700
+ let(:expected_source) do
701
+ <<-END
702
+ require 'active_support/inflector'
703
+
704
+ class String
705
+ def words
706
+ split(' ')
707
+ end
708
+ end
709
+
710
+ describe 'string' do
711
+ it 'has a word' do
712
+ expect(subject.words.size).to eq(1)
713
+ end
714
+ end
715
+ END
716
+ end
717
+
718
+ it 'converts into `expect(subject.words.size).to eq(1)` form' do
719
+ have_object.convert_to_standard_expectation!
720
+ rewritten_source.should == expected_source
721
+ end
722
+
723
+ it 'adds record "`expect(obj).to have(n).words` -> `expect(obj.words.size).to eq(n)`"' do
724
+ have_object.convert_to_standard_expectation!
725
+ record.original_syntax.should == 'expect(obj).to have(n).words'
726
+ record.converted_syntax.should == 'expect(obj.words.size).to eq(n)'
727
+ end
728
+ end
729
+
730
+ context 'and ActiveSupport::Inflector.pluralize is not available in the spec' do
731
+ let(:source) do
732
+ <<-END
733
+ class String
734
+ def words
735
+ split(' ')
736
+ end
737
+ end
738
+
739
+ describe 's' do
740
+ it 'has a character' do
741
+ expect(subject).to have(1).word
742
+ end
743
+ end
744
+ END
745
+ end
746
+
747
+ let(:expected_source) do
748
+ <<-END
749
+ class String
750
+ def words
751
+ split(' ')
752
+ end
753
+ end
754
+
755
+ describe 's' do
756
+ it 'has a character' do
757
+ expect(subject.size).to eq(1)
758
+ end
759
+ end
760
+ END
761
+ end
762
+
763
+ it 'converts into `expect(subject.size).to eq(1)` form' do
764
+ have_object.convert_to_standard_expectation!
765
+ rewritten_source.should == expected_source
766
+ end
767
+
768
+ it 'adds record "`expect(collection).to have(n).items` -> `expect(collection.size).to eq(n)`"' do
769
+ have_object.convert_to_standard_expectation!
770
+ record.original_syntax.should == 'expect(collection).to have(n).items'
771
+ record.converted_syntax.should == 'expect(collection.size).to eq(n)'
772
+ end
773
+ end
774
+ end
775
+ end
776
+
777
+ context 'without runtime information' do
778
+ let(:source) do
779
+ <<-END
780
+ require 'active_support/inflector'
781
+
782
+ class String
783
+ def words
784
+ split(' ')
785
+ end
786
+ end
787
+
788
+ describe 'string' do
789
+ it 'has a word' do
790
+ expect(subject).to have(1).word
791
+ end
792
+ end
793
+ END
794
+ end
795
+
796
+ let(:expected_source) do
797
+ <<-END
798
+ require 'active_support/inflector'
799
+
800
+ class String
801
+ def words
802
+ split(' ')
803
+ end
804
+ end
805
+
806
+ describe 'string' do
807
+ it 'has a word' do
808
+ expect(subject.size).to eq(1)
809
+ end
810
+ end
811
+ END
812
+ end
813
+
814
+ it 'converts into `expect(subject.size).to eq(1)` form' do
815
+ have_object.convert_to_standard_expectation!
816
+ rewritten_source.should == expected_source
817
+ end
818
+
819
+ it 'adds record "`expect(collection).to have(n).items` -> `expect(collection.size).to eq(n)`"' do
820
+ have_object.convert_to_standard_expectation!
821
+ record.original_syntax.should == 'expect(collection).to have(n).items'
822
+ record.converted_syntax.should == 'expect(collection.size).to eq(n)'
823
+ end
824
+ end
825
+ end
826
+
827
+ context 'when it is `expect(subject).to have(2).errors_on(:name)` form' do
828
+ let(:have_object) { expect_object.have_matcher }
829
+
830
+ context 'with runtime information' do
831
+ include_context 'dynamic analysis objects'
832
+
833
+ context 'and subject responds to #errors_on' do
834
+ let(:source) do
835
+ <<-END
836
+ class SomeModel
837
+ def errors_on(attribute)
838
+ [:foo, :bar]
839
+ end
840
+ end
841
+
842
+ describe SomeModel do
843
+ it 'has 2 errors on name' do
844
+ expect(subject).to have(2).errors_on(:name)
845
+ end
846
+ end
847
+ END
848
+ end
849
+
850
+ let(:expected_source) do
851
+ <<-END
852
+ class SomeModel
853
+ def errors_on(attribute)
854
+ [:foo, :bar]
855
+ end
856
+ end
857
+
858
+ describe SomeModel do
859
+ it 'has 2 errors on name' do
860
+ expect(subject.errors_on(:name).size).to eq(2)
861
+ end
862
+ end
863
+ END
864
+ end
865
+
866
+ it 'converts into `expect(subject.errors_on(:name).size).to eq(2)` form' do
867
+ have_object.convert_to_standard_expectation!
868
+ rewritten_source.should == expected_source
869
+ end
870
+
871
+ it 'adds record ' +
872
+ '"`expect(obj).to have(n).errors_on(...)` -> `expect(obj.errors_on(...).size).to eq(n)`"' do
873
+ have_object.convert_to_standard_expectation!
874
+ record.original_syntax.should == 'expect(obj).to have(n).errors_on(...)'
875
+ record.converted_syntax.should == 'expect(obj.errors_on(...).size).to eq(n)'
876
+ end
877
+ end
878
+
879
+ context 'and #errors_on is a private method' do
880
+ let(:source) do
881
+ <<-END
882
+ class SomeModel
883
+ private
884
+
885
+ def errors_on(attribute)
886
+ [:foo, :bar]
887
+ end
888
+ end
889
+
890
+ describe SomeModel do
891
+ it 'has 2 errors on name' do
892
+ expect(subject).to have(2).errors_on(:name)
893
+ end
894
+ end
895
+ END
896
+ end
897
+
898
+ let(:expected_source) do
899
+ <<-END
900
+ class SomeModel
901
+ private
902
+
903
+ def errors_on(attribute)
904
+ [:foo, :bar]
905
+ end
906
+ end
907
+
908
+ describe SomeModel do
909
+ it 'has 2 errors on name' do
910
+ expect(subject.send(:errors_on, :name).size).to eq(2)
911
+ end
912
+ end
913
+ END
914
+ end
915
+
916
+ it 'converts into `expect(subject.send(:errors_on, :name).size).to eq(2)` form' do
917
+ have_object.convert_to_standard_expectation!
918
+ rewritten_source.should == expected_source
919
+ end
920
+
921
+ it 'adds record ' +
922
+ '"`expect(obj).to have(n).errors_on(...)` -> `expect(obj.send(:errors_on, ...).size).to eq(n)`"' do
923
+ have_object.convert_to_standard_expectation!
924
+ record.original_syntax.should == 'expect(obj).to have(n).errors_on(...)'
925
+ record.converted_syntax.should == 'expect(obj.send(:errors_on, ...).size).to eq(n)'
926
+ end
927
+ end
928
+ end
929
+
930
+ context 'without runtime information' do
931
+ let(:source) do
932
+ <<-END
933
+ class SomeModel
934
+ def errors_on(attribute)
935
+ [:foo, :bar]
936
+ end
937
+ end
938
+
939
+ describe SomeModel do
940
+ it 'has 2 errors on name' do
941
+ expect(subject).to have(2).errors_on(:name)
942
+ end
943
+ end
944
+ END
945
+ end
946
+
947
+ let(:expected_source) do
948
+ <<-END
949
+ class SomeModel
950
+ def errors_on(attribute)
951
+ [:foo, :bar]
952
+ end
953
+ end
954
+
955
+ describe SomeModel do
956
+ it 'has 2 errors on name' do
957
+ expect(subject.errors_on(:name).size).to eq(2)
958
+ end
959
+ end
960
+ END
961
+ end
962
+
963
+ it 'converts into `expect(subject.errors_on(:name).size).to eq(2)` form' do
964
+ have_object.convert_to_standard_expectation!
965
+ rewritten_source.should == expected_source
966
+ end
967
+
968
+ it 'adds record ' +
969
+ '"`expect(obj).to have(n).errors_on(...)` -> `expect(obj.errors_on(...).size).to eq(n)`"' do
970
+ have_object.convert_to_standard_expectation!
971
+ record.original_syntax.should == 'expect(obj).to have(n).errors_on(...)'
972
+ record.converted_syntax.should == 'expect(obj.errors_on(...).size).to eq(n)'
973
+ end
974
+ end
975
+ end
621
976
  end
622
977
  end
623
978
  end