transpec 1.9.3 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +1 -1
  4. data/CHANGELOG.md +5 -0
  5. data/CONTRIBUTING.md +19 -0
  6. data/README.md +78 -9
  7. data/README.md.erb +68 -10
  8. data/lib/transpec/annotatable.rb +16 -0
  9. data/lib/transpec/cli.rb +35 -27
  10. data/lib/transpec/configuration.rb +1 -0
  11. data/lib/transpec/conversion_error.rb +23 -0
  12. data/lib/transpec/converter.rb +59 -50
  13. data/lib/transpec/dynamic_analyzer.rb +13 -29
  14. data/lib/transpec/dynamic_analyzer/rewriter.rb +3 -10
  15. data/lib/transpec/dynamic_analyzer/runtime_data.rb +16 -8
  16. data/lib/transpec/file_finder.rb +1 -1
  17. data/lib/transpec/git.rb +1 -1
  18. data/lib/transpec/option_parser.rb +12 -10
  19. data/lib/transpec/project.rb +3 -3
  20. data/lib/transpec/record.rb +19 -2
  21. data/lib/transpec/report.rb +29 -13
  22. data/lib/transpec/rspec_version.rb +7 -7
  23. data/lib/transpec/static_context_inspector.rb +1 -5
  24. data/lib/transpec/syntax.rb +11 -16
  25. data/lib/transpec/syntax/be_boolean.rb +1 -1
  26. data/lib/transpec/syntax/be_close.rb +1 -1
  27. data/lib/transpec/syntax/current_example.rb +88 -0
  28. data/lib/transpec/syntax/double.rb +1 -1
  29. data/lib/transpec/syntax/example.rb +60 -54
  30. data/lib/transpec/syntax/have.rb +27 -15
  31. data/lib/transpec/syntax/have/have_record.rb +12 -0
  32. data/lib/transpec/syntax/have/source_builder.rb +18 -16
  33. data/lib/transpec/syntax/its.rb +12 -11
  34. data/lib/transpec/syntax/matcher_definition.rb +1 -1
  35. data/lib/transpec/syntax/method_stub.rb +3 -7
  36. data/lib/transpec/syntax/mixin/matcher_owner.rb +2 -2
  37. data/lib/transpec/syntax/mixin/monkey_patch.rb +3 -5
  38. data/lib/transpec/syntax/mixin/monkey_patch_any_instance.rb +2 -4
  39. data/lib/transpec/syntax/mixin/owned_matcher.rb +1 -4
  40. data/lib/transpec/syntax/mixin/send.rb +7 -9
  41. data/lib/transpec/syntax/oneliner_should.rb +4 -4
  42. data/lib/transpec/syntax/operator.rb +27 -11
  43. data/lib/transpec/syntax/pending.rb +110 -0
  44. data/lib/transpec/syntax/raise_error.rb +1 -1
  45. data/lib/transpec/syntax/receive.rb +4 -4
  46. data/lib/transpec/syntax/rspec_configure/framework.rb +3 -3
  47. data/lib/transpec/syntax/should.rb +2 -2
  48. data/lib/transpec/syntax/should_receive.rb +3 -3
  49. data/lib/transpec/util.rb +38 -6
  50. data/lib/transpec/version.rb +2 -2
  51. data/spec/support/file_helper.rb +1 -1
  52. data/spec/support/shared_context.rb +3 -8
  53. data/spec/transpec/cli_spec.rb +63 -1
  54. data/spec/transpec/configuration_spec.rb +1 -0
  55. data/spec/transpec/converter_spec.rb +106 -15
  56. data/spec/transpec/dynamic_analyzer/rewriter_spec.rb +12 -52
  57. data/spec/transpec/dynamic_analyzer_spec.rb +2 -2
  58. data/spec/transpec/option_parser_spec.rb +3 -2
  59. data/spec/transpec/report_spec.rb +33 -4
  60. data/spec/transpec/rspec_version_spec.rb +5 -2
  61. data/spec/transpec/syntax/current_example_spec.rb +267 -0
  62. data/spec/transpec/syntax/example_spec.rb +156 -122
  63. data/spec/transpec/syntax/have_spec.rb +43 -32
  64. data/spec/transpec/syntax/method_stub_spec.rb +8 -0
  65. data/spec/transpec/syntax/operator_spec.rb +67 -2
  66. data/spec/transpec/syntax/pending_spec.rb +375 -0
  67. metadata +12 -4
  68. data/lib/transpec/context_error.rb +0 -23
@@ -4,8 +4,8 @@ module Transpec
4
4
  # http://semver.org/
5
5
  module Version
6
6
  MAJOR = 1
7
- MINOR = 9
8
- PATCH = 3
7
+ MINOR = 10
8
+ PATCH = 0
9
9
 
10
10
  def self.to_s
11
11
  [MAJOR, MINOR, PATCH].join('.')
@@ -9,7 +9,7 @@ module FileHelper
9
9
  file_path = File.expand_path(file_path)
10
10
 
11
11
  dir_path = File.dirname(file_path)
12
- FileUtils.makedirs(dir_path) unless File.exists?(dir_path)
12
+ FileUtils.makedirs(dir_path) unless File.exist?(dir_path)
13
13
 
14
14
  File.open(file_path, 'w') do |file|
15
15
  case content
@@ -2,9 +2,11 @@
2
2
 
3
3
  # This context requires `source` to be defined with #let.
4
4
  shared_context 'parsed objects' do
5
+ let(:source_path) { '(string)' }
6
+
5
7
  let(:source_buffer) do
6
8
  require 'parser'
7
- buffer = Parser::Source::Buffer.new('(string)')
9
+ buffer = Parser::Source::Buffer.new(source_path)
8
10
  buffer.source = source
9
11
  buffer
10
12
  end
@@ -34,13 +36,6 @@ shared_context 'dynamic analysis objects' do
34
36
 
35
37
  let(:source_path) { 'spec/example_spec.rb' }
36
38
 
37
- let(:source_buffer) do
38
- require 'parser'
39
- buffer = Parser::Source::Buffer.new(source_path)
40
- buffer.source = source
41
- buffer
42
- end
43
-
44
39
  runtime_data_cache = {}
45
40
 
46
41
  let(:runtime_data) do
@@ -185,7 +185,7 @@ module Transpec
185
185
  let(:args) { ['--skip-dynamic-analysis', file_path] }
186
186
 
187
187
  it 'skips dynamic analysis' do
188
- DynamicAnalyzer.any_instance.should_not_receive(:analysis)
188
+ DynamicAnalyzer.any_instance.should_not_receive(:analyze)
189
189
  cli.should_receive(:convert_file)
190
190
  cli.run(args)
191
191
  end
@@ -242,6 +242,68 @@ module Transpec
242
242
  cli.convert_file(file_path)
243
243
  end
244
244
  end
245
+
246
+ context 'when it did a less accurate conversion due to a lack of runtime information' do
247
+ let(:source) do
248
+ <<-END
249
+ describe 'example group' do
250
+ it 'is an example' do
251
+ expect(obj).to have(2).items
252
+ end
253
+ end
254
+ END
255
+ end
256
+
257
+ it 'warns to user' do
258
+ cli.should_receive(:warn) do |message|
259
+ message.should =~ /converted.+but.+incorrect/i
260
+ end
261
+
262
+ cli.convert_file(file_path)
263
+ end
264
+ end
265
+
266
+ context 'when both conversion errors and less accurate records are reported' do
267
+ let(:source) do
268
+ <<-END
269
+ describe 'example group' do
270
+ it 'is first' do
271
+ expect(obj).to have(1).item
272
+ end
273
+
274
+ class Klass
275
+ def second
276
+ 2.should == 2
277
+ end
278
+ end
279
+
280
+ it 'is an example' do
281
+ Klass.new.some_method
282
+ end
283
+
284
+ it 'is third' do
285
+ expect(obj).to have(3).items
286
+ end
287
+ end
288
+ END
289
+ end
290
+
291
+ it 'displays them in order of line number' do
292
+ times = 1
293
+
294
+ cli.should_receive(:warn).exactly(3).times do |message|
295
+ line_number = case times
296
+ when 1 then 3
297
+ when 2 then 8
298
+ when 3 then 17
299
+ end
300
+ message.should include(":#{line_number}:")
301
+ times += 1
302
+ end
303
+
304
+ cli.convert_file(file_path)
305
+ end
306
+ end
245
307
  end
246
308
  end
247
309
  end
@@ -15,6 +15,7 @@ module Transpec
15
15
  [:convert_stub?, true],
16
16
  [:convert_have_items?, true],
17
17
  [:convert_its?, true],
18
+ [:convert_pending?, true],
18
19
  [:convert_deprecated_method?, true],
19
20
  [:parenthesize_matcher_arg?, true],
20
21
  [:add_receiver_arg_to_any_instance_implementation_block?, true],
@@ -117,6 +117,11 @@ module Transpec
117
117
  it 'does not convert the expectation to non-monkey-patch syntax' do
118
118
  should == source
119
119
  end
120
+
121
+ it 'adds the conversion error to the report' do
122
+ converter.convert(source)
123
+ converter.report.should have(1).conversion_error
124
+ end
120
125
  end
121
126
  end
122
127
 
@@ -913,15 +918,101 @@ module Transpec
913
918
  describe '#process_example' do
914
919
  let(:example_object) { double('example_object').as_null_object }
915
920
 
921
+ shared_examples 'does nothing' do
922
+ it 'does nothing' do
923
+ example_object.should_not_receive(:convert_pending_to_skip!)
924
+ converter.process_example(example_object)
925
+ end
926
+ end
927
+
928
+ context 'when RSpecVersion#rspec_2_99? returns true' do
929
+ before { rspec_version.stub(:rspec_2_99?).and_return(true) }
930
+
931
+ context 'and Configuration#convert_pending? returns true' do
932
+ before { configuration.convert_pending = true }
933
+
934
+ it 'invokes Example#convert_pending_to_skip!' do
935
+ example_object.should_receive(:convert_pending_to_skip!)
936
+ converter.process_example(example_object)
937
+ end
938
+ end
939
+
940
+ context 'and Configuration#convert_pending? returns false' do
941
+ before { configuration.convert_pending = false }
942
+ include_examples 'does nothing'
943
+ end
944
+ end
945
+
946
+ context 'when RSpecVersion#rspec_2_99? returns false' do
947
+ before { rspec_version.stub(:rspec_2_99?).and_return(false) }
948
+
949
+ context 'and Configuration#convert_pending? returns true' do
950
+ before { configuration.convert_pending = true }
951
+ include_examples 'does nothing'
952
+ end
953
+
954
+ context 'and Configuration#convert_pending? returns false' do
955
+ before { configuration.convert_pending = false }
956
+ include_examples 'does nothing'
957
+ end
958
+ end
959
+ end
960
+
961
+ describe '#process_pending' do
962
+ let(:pending_object) { double('pending_object').as_null_object }
963
+
964
+ shared_examples 'does nothing' do
965
+ it 'does nothing' do
966
+ pending_object.should_not_receive(:convert_deprecated_syntax!)
967
+ converter.process_pending(pending_object)
968
+ end
969
+ end
970
+
971
+ context 'when RSpecVersion#rspec_2_99? returns true' do
972
+ before { rspec_version.stub(:rspec_2_99?).and_return(true) }
973
+
974
+ context 'and Configuration#convert_pending? returns true' do
975
+ before { configuration.convert_pending = true }
976
+
977
+ it 'invokes Example#convert_deprecated_syntax!' do
978
+ pending_object.should_receive(:convert_deprecated_syntax!)
979
+ converter.process_pending(pending_object)
980
+ end
981
+ end
982
+
983
+ context 'and Configuration#convert_pending? returns false' do
984
+ before { configuration.convert_pending = false }
985
+ include_examples 'does nothing'
986
+ end
987
+ end
988
+
989
+ context 'when RSpecVersion#rspec_2_99? returns false' do
990
+ before { rspec_version.stub(:rspec_2_99?).and_return(false) }
991
+
992
+ context 'and Configuration#convert_pending? returns true' do
993
+ before { configuration.convert_pending = true }
994
+ include_examples 'does nothing'
995
+ end
996
+
997
+ context 'and Configuration#convert_pending? returns false' do
998
+ before { configuration.convert_pending = false }
999
+ include_examples 'does nothing'
1000
+ end
1001
+ end
1002
+ end
1003
+
1004
+ describe '#process_current_example' do
1005
+ let(:current_example_object) { double('current_example_object').as_null_object }
1006
+
916
1007
  context 'when RSpecVersion#yielded_example_available? returns true' do
917
1008
  before { rspec_version.stub(:yielded_example_available?).and_return(true) }
918
1009
 
919
1010
  context 'and Configuration#convert_deprecated_method? is true' do
920
1011
  before { configuration.convert_deprecated_method = true }
921
1012
 
922
- it 'invokes Example#convert!' do
923
- example_object.should_receive(:convert!)
924
- converter.process_example(example_object)
1013
+ it 'invokes CurrentExample#convert!' do
1014
+ current_example_object.should_receive(:convert!)
1015
+ converter.process_current_example(current_example_object)
925
1016
  end
926
1017
  end
927
1018
 
@@ -929,8 +1020,8 @@ module Transpec
929
1020
  before { configuration.convert_deprecated_method = false }
930
1021
 
931
1022
  it 'does nothing' do
932
- example_object.should_not_receive(:convert!)
933
- converter.process_example(example_object)
1023
+ current_example_object.should_not_receive(:convert!)
1024
+ converter.process_current_example(current_example_object)
934
1025
  end
935
1026
  end
936
1027
  end
@@ -942,8 +1033,8 @@ module Transpec
942
1033
  before { configuration.convert_deprecated_method = true }
943
1034
 
944
1035
  it 'does nothing' do
945
- example_object.should_not_receive(:convert!)
946
- converter.process_example(example_object)
1036
+ current_example_object.should_not_receive(:convert!)
1037
+ converter.process_current_example(current_example_object)
947
1038
  end
948
1039
  end
949
1040
  end
@@ -1041,9 +1132,9 @@ module Transpec
1041
1132
  end
1042
1133
  end
1043
1134
 
1044
- context 'when RSpecVersion#migration_term_of_any_instance_implementation_block? returns true' do
1135
+ context 'when RSpecVersion#rspec_2_99? returns true' do
1045
1136
  before do
1046
- rspec_version.stub(:migration_term_of_any_instance_implementation_block?).and_return(true)
1137
+ rspec_version.stub(:rspec_2_99?).and_return(true)
1047
1138
  end
1048
1139
 
1049
1140
  context 'and Configuration#convert_deprecated_method? returns true' do
@@ -1078,9 +1169,9 @@ module Transpec
1078
1169
  end
1079
1170
  end
1080
1171
 
1081
- context 'when RSpecVersion#migration_term_of_any_instance_implementation_block? returns false' do
1172
+ context 'when RSpecVersion#rspec_2_99? returns false' do
1082
1173
  before do
1083
- rspec_version.stub(:migration_term_of_any_instance_implementation_block?).and_return(false)
1174
+ rspec_version.stub(:rspec_2_99?).and_return(false)
1084
1175
  end
1085
1176
 
1086
1177
  it 'does not invoke RSpecConfigure.mocks.yield_receiver_to_any_instance_implementation_blocks=' do
@@ -1115,9 +1206,9 @@ module Transpec
1115
1206
  describe '#process_any_instance_block' do
1116
1207
  let(:messaging_host) { double('messaging host').as_null_object }
1117
1208
 
1118
- context 'when RSpecVersion#migration_term_of_any_instance_implementation_block? returns true' do
1209
+ context 'when RSpecVersion#rspec_2_99? returns true' do
1119
1210
  before do
1120
- rspec_version.stub(:migration_term_of_any_instance_implementation_block?).and_return(true)
1211
+ rspec_version.stub(:rspec_2_99?).and_return(true)
1121
1212
  end
1122
1213
 
1123
1214
  context 'and Configuration#convert_deprecated_method? returns true' do
@@ -1156,9 +1247,9 @@ module Transpec
1156
1247
  end
1157
1248
  end
1158
1249
 
1159
- context 'when RSpecVersion#migration_term_of_any_instance_implementation_block? returns false' do
1250
+ context 'when RSpecVersion#rspec_2_99? returns false' do
1160
1251
  before do
1161
- rspec_version.stub(:migration_term_of_any_instance_implementation_block?).and_return(false)
1252
+ rspec_version.stub(:rspec_2_99?).and_return(false)
1162
1253
  end
1163
1254
 
1164
1255
  it 'does nothing' do
@@ -15,18 +15,14 @@ module Transpec
15
15
 
16
16
  let(:source) do
17
17
  <<-END
18
- it 'is foo' do
19
- subject.should be(foo)
20
- end
18
+ subject.should be(foo)
21
19
  END
22
20
  end
23
21
 
24
22
  # rubocop:disable LineLength
25
23
  let(:expected_source) do
26
24
  <<-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)
29
- end
25
+ transpec_analyze((transpec_analyze((subject), self, "(string)_12_19", { :should_source_location => [:object, "method(:should).source_location"] }).should be(foo)), self, "(string)_12_34", { :expect_available? => [:context, "self.class.ancestors.any? { |a| a.name.start_with?('RSpec::') } && respond_to?(:expect)"] })
30
26
  END
31
27
  end
32
28
  # rubocop:enable LineLength
@@ -38,22 +34,18 @@ module Transpec
38
34
  context 'when the target includes here document' do
39
35
  let(:source) do
40
36
  <<-END
41
- it 'matches to foo' do
42
- subject.should =~ <<-HEREDOC.gsub('foo', 'bar')
43
- foo
44
- HEREDOC
45
- end
37
+ subject.should =~ <<-HEREDOC.gsub('foo', 'bar')
38
+ foo
39
+ HEREDOC
46
40
  END
47
41
  end
48
42
 
49
43
  # rubocop:disable LineLength
50
44
  let(:expected_source) do
51
45
  <<-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
56
- end
46
+ transpec_analyze((transpec_analyze((subject), self, "(string)_14_21", { :should_source_location => [:object, "method(:should).source_location"] }).should), self, "(string)_14_28", { :"=~_source_location" => [:object, "method(:=~).source_location"], :expect_available? => [:context, "self.class.ancestors.any? { |a| a.name.start_with?('RSpec::') } && respond_to?(:expect)"] }) =~ transpec_analyze((<<-HEREDOC.gsub('foo', 'bar')), self, "(string)_32_61", { :arg_is_enumerable? => [:object, "is_a?(Enumerable)"] })
47
+ foo
48
+ HEREDOC
57
49
  END
58
50
  end
59
51
  # rubocop:enable LineLength
@@ -66,18 +58,14 @@ module Transpec
66
58
  context 'when the target takes block' do
67
59
  let(:source) do
68
60
  <<-END
69
- it 'raises error' do
70
- expect { do_something }.to throw_symbol
71
- end
61
+ expect { do_something }.to throw_symbol
72
62
  END
73
63
  end
74
64
 
75
65
  # rubocop:disable LineLength
76
66
  let(:expected_source) do
77
67
  <<-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
80
- end
68
+ transpec_analyze((expect { do_something }), self, "(string)_14_20", { :expect_source_location => [:context, "method(:expect).source_location"] }).to throw_symbol
81
69
  END
82
70
  end
83
71
  # rubocop:enable LineLength
@@ -87,45 +75,17 @@ module Transpec
87
75
  end
88
76
  end
89
77
 
90
- context 'when the target is only the expression in a block' do
91
- let(:source) do
92
- <<-END
93
- it 'raises error' do
94
- expect
95
- end
96
- END
97
- end
98
-
99
- # rubocop:disable LineLength
100
- let(:expected_source) do
101
- <<-END
102
- it 'raises error' do
103
- transpec_analysis((expect), self, { :expect_source_location => [:context, "method(:expect).source_location"] }, __FILE__, 51, 57)
104
- end
105
- END
106
- end
107
- # rubocop:enable LineLength
108
-
109
- it 'wraps the target properly' do
110
- should == expected_source
111
- end
112
- end
113
-
114
78
  context 'when the target is method invocation without parentheses' do
115
79
  let(:source) do
116
80
  <<-END
117
- it 'raises error' do
118
- expect subject
119
- end
81
+ double 'something'
120
82
  END
121
83
  end
122
84
 
123
85
  # rubocop:disable LineLength
124
86
  let(:expected_source) do
125
87
  <<-END
126
- it 'raises error' do
127
- transpec_analysis((expect subject), self, { :expect_source_location => [:context, "method(:expect).source_location"] }, __FILE__, 51, 65)
128
- end
88
+ transpec_analyze((double 'something'), self, "(string)_14_32", { :double_source_location => [:context, "method(:double).source_location"] })
129
89
  END
130
90
  end
131
91
  # rubocop:enable LineLength
@@ -164,7 +164,7 @@ module Transpec
164
164
  runtime_data.should be_an(DynamicAnalyzer::RuntimeData)
165
165
  end
166
166
 
167
- describe 'its element' do
167
+ describe 'an element of the runtime data' do
168
168
  let(:ast) do
169
169
  source_buffer = Parser::Source::Buffer.new(file_path)
170
170
  source_buffer.source = source
@@ -188,7 +188,7 @@ module Transpec
188
188
  end
189
189
 
190
190
  it 'has result of requested analysis' do
191
- element[:available_query_methods].result.should =~ %w(size count length)
191
+ element[:available_query_methods].should =~ %w(size count length)
192
192
  end
193
193
  end
194
194
  end