transpec 1.2.2 → 1.3.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/CHANGELOG.md +9 -0
- data/README.md +36 -16
- data/README.md.erb +36 -16
- data/lib/transpec/option_parser.rb +1 -1
- data/lib/transpec/syntax/have.rb +126 -39
- data/lib/transpec/syntax/its.rb +15 -2
- data/lib/transpec/syntax/method_stub.rb +4 -4
- data/lib/transpec/syntax/mixin/any_instance.rb +43 -4
- data/lib/transpec/syntax/mixin/send.rb +4 -0
- data/lib/transpec/syntax/should_receive.rb +9 -9
- data/lib/transpec/version.rb +2 -2
- data/spec/transpec/cli_spec.rb +2 -2
- data/spec/transpec/converter_spec.rb +2 -2
- data/spec/transpec/static_context_inspector_spec.rb +5 -5
- data/spec/transpec/syntax/have_spec.rb +355 -0
- data/spec/transpec/syntax/its_spec.rb +49 -24
- data/spec/transpec/syntax/method_stub_spec.rb +467 -323
- data/spec/transpec/syntax/should_receive_spec.rb +212 -24
- data/transpec.gemspec +1 -0
- metadata +15 -1
@@ -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
|
-
|
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
|
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
|
-
|
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
|
@@ -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
|
-
|
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
|
108
|
-
|
109
|
-
|
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
|
-
'
|
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(
|
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(
|
195
|
+
'allow_any_instance_of(Klass).'
|
196
196
|
else
|
197
197
|
'allow(obj).'
|
198
198
|
end
|
data/lib/transpec/version.rb
CHANGED
data/spec/transpec/cli_spec.rb
CHANGED
@@ -224,14 +224,14 @@ module Transpec
|
|
224
224
|
let(:source) do
|
225
225
|
<<-END
|
226
226
|
describe 'example group' do
|
227
|
-
class
|
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
|
-
|
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
|
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
|
-
|
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
|
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
|
500
|
+
class Klass
|
501
501
|
def some_method
|
502
502
|
target
|
503
503
|
end
|
504
504
|
end
|
505
505
|
|
506
|
-
|
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
|
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 {
|
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
|