transpec 0.2.6 → 1.0.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +1 -1
  4. data/CHANGELOG.md +10 -0
  5. data/README.md +111 -56
  6. data/README.md.erb +117 -62
  7. data/lib/transpec/ast/node.rb +41 -0
  8. data/lib/transpec/base_rewriter.rb +55 -0
  9. data/lib/transpec/cli.rb +43 -153
  10. data/lib/transpec/configuration.rb +13 -9
  11. data/lib/transpec/{rewriter.rb → converter.rb} +44 -71
  12. data/lib/transpec/dynamic_analyzer/rewriter.rb +94 -0
  13. data/lib/transpec/dynamic_analyzer/runtime_data.rb +27 -0
  14. data/lib/transpec/dynamic_analyzer.rb +166 -0
  15. data/lib/transpec/file_finder.rb +53 -0
  16. data/lib/transpec/option_parser.rb +166 -0
  17. data/lib/transpec/{context.rb → static_context_inspector.rb} +2 -2
  18. data/lib/transpec/syntax/be_close.rb +7 -9
  19. data/lib/transpec/syntax/double.rb +6 -10
  20. data/lib/transpec/syntax/expect.rb +35 -0
  21. data/lib/transpec/syntax/have.rb +195 -0
  22. data/lib/transpec/syntax/method_stub.rb +22 -27
  23. data/lib/transpec/syntax/mixin/allow_no_message.rb +73 -0
  24. data/lib/transpec/syntax/mixin/any_instance.rb +22 -0
  25. data/lib/transpec/syntax/mixin/expectizable.rb +26 -0
  26. data/lib/transpec/syntax/mixin/have_matcher.rb +23 -0
  27. data/lib/transpec/syntax/mixin/monkey_patch.rb +37 -0
  28. data/lib/transpec/syntax/mixin/send.rb +109 -0
  29. data/lib/transpec/syntax/{matcher.rb → operator_matcher.rb} +27 -14
  30. data/lib/transpec/syntax/raise_error.rb +6 -10
  31. data/lib/transpec/syntax/rspec_configure.rb +29 -28
  32. data/lib/transpec/syntax/should.rb +45 -15
  33. data/lib/transpec/syntax/should_receive.rb +44 -16
  34. data/lib/transpec/syntax.rb +29 -21
  35. data/lib/transpec/util.rb +12 -2
  36. data/lib/transpec/version.rb +3 -3
  37. data/spec/spec_helper.rb +8 -6
  38. data/spec/support/cache_helper.rb +50 -0
  39. data/spec/support/shared_context.rb +49 -1
  40. data/spec/transpec/ast/node_spec.rb +65 -0
  41. data/spec/transpec/cli_spec.rb +33 -242
  42. data/spec/transpec/commit_message_spec.rb +2 -2
  43. data/spec/transpec/configuration_spec.rb +12 -8
  44. data/spec/transpec/{rewriter_spec.rb → converter_spec.rb} +198 -148
  45. data/spec/transpec/dynamic_analyzer/rewriter_spec.rb +183 -0
  46. data/spec/transpec/dynamic_analyzer_spec.rb +164 -0
  47. data/spec/transpec/file_finder_spec.rb +118 -0
  48. data/spec/transpec/option_parser_spec.rb +185 -0
  49. data/spec/transpec/{context_spec.rb → static_context_inspector_spec.rb} +27 -12
  50. data/spec/transpec/syntax/be_close_spec.rb +8 -4
  51. data/spec/transpec/syntax/double_spec.rb +105 -12
  52. data/spec/transpec/syntax/expect_spec.rb +83 -0
  53. data/spec/transpec/syntax/have_spec.rb +599 -0
  54. data/spec/transpec/syntax/method_stub_spec.rb +276 -115
  55. data/spec/transpec/syntax/{matcher_spec.rb → operator_matcher_spec.rb} +277 -98
  56. data/spec/transpec/syntax/raise_error_spec.rb +92 -46
  57. data/spec/transpec/syntax/should_receive_spec.rb +298 -92
  58. data/spec/transpec/syntax/should_spec.rb +230 -44
  59. data/spec/transpec/util_spec.rb +2 -9
  60. data/tasks/lib/transpec_demo.rb +1 -1
  61. data/tasks/lib/transpec_test.rb +5 -7
  62. data/tasks/test.rake +5 -1
  63. data/transpec.gemspec +1 -1
  64. metadata +46 -22
  65. data/lib/transpec/syntax/able_to_allow_no_message.rb +0 -73
  66. data/lib/transpec/syntax/able_to_target_any_instance.rb +0 -24
  67. data/lib/transpec/syntax/expectizable.rb +0 -27
  68. data/lib/transpec/syntax/send_node_syntax.rb +0 -57
@@ -17,22 +17,6 @@ module Transpec
17
17
  end
18
18
  end
19
19
 
20
- describe '#forced?' do
21
- subject { cli.forced? }
22
-
23
- context 'by default' do
24
- it { should be_false }
25
- end
26
- end
27
-
28
- describe '#generates_commit_message?' do
29
- subject { cli.generates_commit_message? }
30
-
31
- context 'by default' do
32
- it { should be_false }
33
- end
34
- end
35
-
36
20
  describe '#run' do
37
21
  include_context 'isolated environment'
38
22
 
@@ -53,12 +37,13 @@ module Transpec
53
37
  before do
54
38
  cli.stub(:puts)
55
39
  cli.stub(:warn)
40
+ DynamicAnalyzer.any_instance.stub(:analyze).and_return(DynamicAnalyzer::RuntimeData.new)
56
41
  create_file(file_path, file_content)
57
42
  end
58
43
 
59
44
  shared_examples 'rewrites files' do
60
45
  it 'rewrites files' do
61
- cli.should_receive(:process_file)
46
+ cli.should_receive(:convert_file)
62
47
  cli.run(args)
63
48
  end
64
49
 
@@ -76,11 +61,9 @@ module Transpec
76
61
  context 'and the repository is not clean' do
77
62
  before { Git.stub(:clean?).and_return(false) }
78
63
 
79
- context '#forced? is false' do
80
- before { cli.stub(:forced?).and_return(false) }
81
-
64
+ context '--force option is not specified' do
82
65
  it 'aborts processing' do
83
- cli.should_not_receive(:process_file)
66
+ cli.should_not_receive(:convert_file)
84
67
  cli.run(args).should be_false
85
68
  end
86
69
 
@@ -94,7 +77,7 @@ module Transpec
94
77
  end
95
78
 
96
79
  context '#forced? is true' do
97
- before { cli.stub(:forced?).and_return(true) }
80
+ before { args << '--force' }
98
81
  include_examples 'rewrites files'
99
82
  end
100
83
  end
@@ -135,8 +118,8 @@ module Transpec
135
118
  end
136
119
 
137
120
  it 'continues processing files' do
138
- cli.should_receive(:puts).with("Processing #{invalid_syntax_file_path}")
139
- cli.should_receive(:puts).with("Processing #{valid_syntax_file_path}")
121
+ cli.should_receive(:puts).with("Converting #{invalid_syntax_file_path}")
122
+ cli.should_receive(:puts).with("Converting #{valid_syntax_file_path}")
140
123
  cli.run(args)
141
124
  end
142
125
  end
@@ -144,41 +127,25 @@ module Transpec
144
127
  context 'when any other error is raised while running' do
145
128
  let(:args) { ['non-existent-file'] }
146
129
 
147
- it 'return false' do
148
- should be_false
149
- end
150
-
151
- it 'prints message of the exception' do
152
- cli.should_receive(:warn).with(/No such file or directory/)
153
- cli.run(args)
130
+ it 'does not catch the error' do
131
+ -> { cli.run(args) }.should raise_error
154
132
  end
155
133
  end
156
134
 
157
- context 'when no target paths are specified' do
158
- let(:args) { [] }
135
+ context 'when -s/--skip-dynamic-analysis option is specified' do
136
+ let(:args) { ['--skip-dynamic-analysis', file_path] }
159
137
 
160
- context 'and there is "spec" directory' do
161
- let(:file_path) { 'spec/example_spec.rb' }
162
-
163
- it 'targets files in the "spec" directoy' do
164
- cli.should_receive(:target_files).with(['spec'])
165
- cli.run(args)
166
- end
167
- end
168
-
169
- context 'and there is not "spec" directory' do
170
- let(:file_path) { 'example_spec.rb' }
171
-
172
- it 'aborts' do
173
- should be_false
174
- end
138
+ it 'skips dynamic analysis' do
139
+ DynamicAnalyzer.any_instance.should_not_receive(:analysis)
140
+ cli.should_receive(:convert_file)
141
+ cli.run(args)
175
142
  end
176
143
  end
177
144
 
178
- context 'when -m/--commit-message option is specified' do
145
+ context 'when -m/--generate-commit-message option is specified' do
179
146
  include_context 'inside of git repository'
180
147
 
181
- let(:args) { ['--force', '--commit-message', file_path] }
148
+ let(:args) { ['--force', '--generate-commit-message', file_path] }
182
149
 
183
150
  context 'and any conversion is done' do
184
151
  it 'writes commit message to .git/COMMIT_EDITMSG' do
@@ -196,9 +163,23 @@ module Transpec
196
163
  end
197
164
  end
198
165
  end
166
+
167
+ context 'when -c/--rspec-command option is specified' do
168
+ include_context 'inside of git repository'
169
+
170
+ let(:args) { ['--force', '--rspec-command', 'rspec --profile'] }
171
+
172
+ it 'passes the command to DynamicAnalyzer' do
173
+ DynamicAnalyzer.should_receive(:new) do |arg|
174
+ arg[:rspec_command].should == 'rspec --profile'
175
+ end.and_call_original
176
+
177
+ cli.run(args)
178
+ end
179
+ end
199
180
  end
200
181
 
201
- describe '#process_file' do
182
+ describe '#convert_file' do
202
183
  include_context 'isolated environment'
203
184
 
204
185
  let(:file_path) { 'example.rb' }
@@ -231,197 +212,7 @@ module Transpec
231
212
  message.should =~ /context/i
232
213
  end
233
214
 
234
- cli.process_file(file_path)
235
- end
236
- end
237
- end
238
-
239
- describe '#parse_options' do
240
- subject { cli.parse_options(args) }
241
- let(:args) { ['some_file', '--negative-form', 'to_not', 'some_dir'] }
242
-
243
- it 'return non-option arguments' do
244
- should == ['some_file', 'some_dir']
245
- end
246
-
247
- it 'does not mutate the passed array' do
248
- cli.parse_options(args)
249
- args.should == ['some_file', '--negative-form', 'to_not', 'some_dir']
250
- end
251
-
252
- describe '-f/--force option' do
253
- let(:args) { ['--force'] }
254
-
255
- it 'sets #forced? true' do
256
- cli.parse_options(args)
257
- cli.should be_forced
258
- end
259
- end
260
-
261
- describe '-m/--commit-message option' do
262
- include_context 'isolated environment'
263
-
264
- let(:args) { ['--commit-message'] }
265
-
266
- context 'when inside of git repository' do
267
- include_context 'inside of git repository'
268
-
269
- it 'sets #generates_commit_message? true' do
270
- cli.parse_options(args)
271
- cli.generates_commit_message?.should be_true
272
- end
273
- end
274
-
275
- context 'when not inside of git repository' do
276
- it 'raises error' do
277
- -> { cli.parse_options(args) }.should raise_error(/not in a Git repository/)
278
- end
279
- end
280
- end
281
-
282
- describe '-d/--disable option' do
283
- [
284
- ['expect_to_matcher', :convert_to_expect_to_matcher?],
285
- ['expect_to_receive', :convert_to_expect_to_receive?],
286
- ['allow_to_receive', :convert_to_allow_to_receive?],
287
- ['deprecated', :replace_deprecated_method?]
288
- ].each do |cli_type, config_attr|
289
- context "when #{cli_type.inspect} is specified" do
290
- let(:args) { ['--disable', cli_type] }
291
-
292
- it "sets Configuration##{config_attr} false" do
293
- cli.parse_options(args)
294
- cli.configuration.send(config_attr).should be_false
295
- end
296
- end
297
- end
298
-
299
- context 'when multiple types are specified with comma' do
300
- let(:args) { ['--disable', 'allow_to_receive,deprecated'] }
301
-
302
- it 'handles all of them' do
303
- cli.parse_options(args)
304
- cli.configuration.convert_to_allow_to_receive?.should be_false
305
- cli.configuration.replace_deprecated_method?.should be_false
306
- end
307
- end
308
-
309
- context 'when unknown type is specified' do
310
- let(:args) { ['--disable', 'unknown'] }
311
-
312
- it 'raises error' do
313
- -> { cli.parse_options(args) }.should raise_error(ArgumentError) { |error|
314
- error.message.should == 'Unknown conversion type "unknown"'
315
- }
316
- end
317
- end
318
- end
319
-
320
- describe '-n/--negative-form option' do
321
- ['not_to', 'to_not'].each do |form|
322
- context "when #{form.inspect} is specified" do
323
- let(:args) { ['--negative-form', form] }
324
-
325
- it "sets Configuration#negative_form_of_to? #{form.inspect}" do
326
- cli.parse_options(args)
327
- cli.configuration.negative_form_of_to.should == form
328
- end
329
- end
330
- end
331
- end
332
-
333
- describe '-p/--no-parentheses-matcher-arg option' do
334
- let(:args) { ['--no-parentheses-matcher-arg'] }
335
-
336
- it 'sets Configuration#parenthesize_matcher_arg? false' do
337
- cli.parse_options(args)
338
- cli.configuration.parenthesize_matcher_arg.should be_false
339
- end
340
- end
341
-
342
- describe '--no-color option' do
343
- before do
344
- Sickill::Rainbow.enabled = true
345
- end
346
-
347
- let(:args) { ['--no-color'] }
348
-
349
- it 'disables color in the output' do
350
- cli.parse_options(args)
351
- Sickill::Rainbow.enabled.should be_false
352
- end
353
- end
354
-
355
- describe '--version option' do
356
- before do
357
- cli.stub(:puts)
358
- cli.stub(:exit)
359
- end
360
-
361
- let(:args) { ['--version'] }
362
-
363
- it 'shows version' do
364
- cli.should_receive(:puts).with(Version.to_s)
365
- cli.parse_options(args)
366
- end
367
-
368
- it 'exits' do
369
- cli.should_receive(:exit)
370
- cli.parse_options(args)
371
- end
372
- end
373
- end
374
-
375
- describe '#target_files' do
376
- include_context 'isolated environment'
377
-
378
- before do
379
- ['file', 'file.rb', 'dir/file', 'dir/file.rb'].each do |path|
380
- create_file(path, '')
381
- end
382
- end
383
-
384
- subject(:target_files) { cli.target_files(paths) }
385
-
386
- context 'when no path is passed' do
387
- let(:paths) { [] }
388
-
389
- it 'returns empty array' do
390
- should be_empty
391
- end
392
- end
393
-
394
- context 'when a file path with .rb extension is passed' do
395
- let(:paths) { ['file.rb'] }
396
-
397
- it 'returns the path' do
398
- should == ['file.rb']
399
- end
400
- end
401
-
402
- context 'when a file path without extension is passed' do
403
- let(:paths) { ['file'] }
404
-
405
- it 'returns the path' do
406
- should == ['file']
407
- end
408
- end
409
-
410
- context 'when a non-existent path is passed' do
411
- let(:paths) { ['non-existent-file'] }
412
-
413
- it 'raises error' do
414
- -> { target_files }.should raise_error(ArgumentError) { |error|
415
- error.message.should == 'No such file or directory "non-existent-file"'
416
- }
417
- end
418
- end
419
-
420
- context 'when a directory path is passed' do
421
- let(:paths) { ['dir'] }
422
-
423
- it 'returns file paths with .rb extension in the directory recursively' do
424
- should == ['dir/file.rb']
215
+ cli.convert_file(file_path)
425
216
  end
426
217
  end
427
218
  end
@@ -9,7 +9,7 @@ module Transpec
9
9
  describe CommitMessage do
10
10
  subject(:commit_message) { CommitMessage.new(report, cli_args) }
11
11
  let(:report) { Report.new }
12
- let(:cli_args) { %w(--force --commit-message) }
12
+ let(:cli_args) { %w(--force --generate-commit-message) }
13
13
 
14
14
  before do
15
15
  report.records << Record.new('obj.stub(:message)', 'allow(obj).to receive(:message)')
@@ -40,7 +40,7 @@ module Transpec
40
40
  body_lines[0].chomp
41
41
  .should match(/^This conversion is done by Transpec \d+\.\d+\.\d+ with the following command:$/)
42
42
  body_lines[1].chomp
43
- .should == ' transpec --force --commit-message'
43
+ .should == ' transpec --force --generate-commit-message'
44
44
  end
45
45
 
46
46
  it 'has blank line after the preface in the body' do
@@ -9,17 +9,21 @@ module Transpec
9
9
 
10
10
  context 'by default' do
11
11
  [
12
- :convert_to_expect_to_matcher?,
13
- :convert_to_expect_to_receive?,
14
- :convert_to_allow_to_receive?,
15
- :replace_deprecated_method?,
16
- :parenthesize_matcher_arg?
17
- ].each do |attribute|
12
+ [:convert_should?, true],
13
+ [:convert_should_receive?, true],
14
+ [:convert_stub?, true],
15
+ [:convert_have_items?, true],
16
+ [:convert_deprecated_method?, true],
17
+ [:parenthesize_matcher_arg?, true],
18
+ [:forced?, false],
19
+ [:skip_dynamic_analysis?, false],
20
+ [:generate_commit_message?, false]
21
+ ].each do |attribute, value|
18
22
  describe "##{attribute}" do
19
23
  subject { configuration.send(attribute) }
20
24
 
21
- it 'is true' do
22
- should be_true
25
+ it "is #{value}" do
26
+ should == value
23
27
  end
24
28
  end
25
29
  end