transpec 0.0.1

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 (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rubocop.yml +13 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +9 -0
  6. data/Guardfile +14 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +37 -0
  9. data/Rakefile +27 -0
  10. data/bin/transpec +8 -0
  11. data/lib/transpec/ast/scanner.rb +51 -0
  12. data/lib/transpec/ast/scope_stack.rb +76 -0
  13. data/lib/transpec/cli.rb +162 -0
  14. data/lib/transpec/configuration.rb +40 -0
  15. data/lib/transpec/git.rb +24 -0
  16. data/lib/transpec/rewriter.rb +109 -0
  17. data/lib/transpec/syntax/double.rb +21 -0
  18. data/lib/transpec/syntax/matcher.rb +60 -0
  19. data/lib/transpec/syntax/method_stub.rb +142 -0
  20. data/lib/transpec/syntax/send_node_syntax.rb +39 -0
  21. data/lib/transpec/syntax/should.rb +49 -0
  22. data/lib/transpec/syntax/should_receive.rb +120 -0
  23. data/lib/transpec/syntax.rb +58 -0
  24. data/lib/transpec/util.rb +50 -0
  25. data/lib/transpec/version.rb +14 -0
  26. data/lib/transpec.rb +17 -0
  27. data/spec/.rubocop.yml +19 -0
  28. data/spec/spec_helper.rb +33 -0
  29. data/spec/spec_spec.rb +54 -0
  30. data/spec/support/file_helper.rb +25 -0
  31. data/spec/support/shared_context.rb +63 -0
  32. data/spec/transpec/ast/scanner_spec.rb +177 -0
  33. data/spec/transpec/ast/scope_stack_spec.rb +94 -0
  34. data/spec/transpec/cli_spec.rb +290 -0
  35. data/spec/transpec/configuration_spec.rb +52 -0
  36. data/spec/transpec/git_spec.rb +85 -0
  37. data/spec/transpec/rewriter_spec.rb +203 -0
  38. data/spec/transpec/syntax/double_spec.rb +88 -0
  39. data/spec/transpec/syntax/matcher_spec.rb +407 -0
  40. data/spec/transpec/syntax/method_stub_spec.rb +386 -0
  41. data/spec/transpec/syntax/should_receive_spec.rb +286 -0
  42. data/spec/transpec/syntax/should_spec.rb +262 -0
  43. data/spec/transpec/util_spec.rb +48 -0
  44. data/transpec.gemspec +32 -0
  45. metadata +233 -0
@@ -0,0 +1,386 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module Transpec
6
+ class Syntax
7
+ describe MethodStub do
8
+ include_context 'parsed objects'
9
+
10
+ subject(:method_stub_object) do
11
+ AST::Scanner.scan(ast) do |node, ancestor_nodes, in_example_group_context|
12
+ next unless MethodStub.target_node?(node)
13
+ return MethodStub.new(
14
+ node,
15
+ ancestor_nodes,
16
+ in_example_group_context?,
17
+ source_rewriter
18
+ )
19
+ end
20
+ fail 'No method stub node is found!'
21
+ end
22
+
23
+ let(:in_example_group_context?) { true }
24
+
25
+ describe '#method_name' do
26
+ let(:source) do
27
+ <<-END
28
+ it 'responds to #foo' do
29
+ subject.stub(:foo)
30
+ end
31
+ END
32
+ end
33
+
34
+ it 'returns the method name' do
35
+ method_stub_object.method_name.should == :stub
36
+ end
37
+ end
38
+
39
+ describe '#allowize!' do
40
+ [:stub, :stub!].each do |method|
41
+ context "when it is `subject.#{method}(:method)` form" do
42
+ let(:source) do
43
+ <<-END
44
+ it 'responds to #foo' do
45
+ subject.#{method}(:foo)
46
+ end
47
+ END
48
+ end
49
+
50
+ let(:expected_source) do
51
+ <<-END
52
+ it 'responds to #foo' do
53
+ allow(subject).to receive(:foo)
54
+ end
55
+ END
56
+ end
57
+
58
+ it 'converts into `allow(subject).to receive(:method)` form' do
59
+ method_stub_object.allowize!
60
+ rewritten_source.should == expected_source
61
+ end
62
+ end
63
+
64
+ context "when it is `subject.#{method}(:method).and_return(value)` form" do
65
+ let(:source) do
66
+ <<-END
67
+ it 'responds to #foo' do
68
+ subject.#{method}(:foo).and_return(value)
69
+ end
70
+ END
71
+ end
72
+
73
+ let(:expected_source) do
74
+ <<-END
75
+ it 'responds to #foo' do
76
+ allow(subject).to receive(:foo).and_return(value)
77
+ end
78
+ END
79
+ end
80
+
81
+ it 'converts into `allow(subject).to receive(:method).and_return(value)` form' do
82
+ method_stub_object.allowize!
83
+ rewritten_source.should == expected_source
84
+ end
85
+ end
86
+
87
+ context "when it is `subject.#{method}(:method).and_raise(RuntimeError)` form" do
88
+ let(:source) do
89
+ <<-END
90
+ it 'responds to #foo' do
91
+ subject.#{method}(:foo).and_raise(RuntimeError)
92
+ end
93
+ END
94
+ end
95
+
96
+ let(:expected_source) do
97
+ <<-END
98
+ it 'responds to #foo' do
99
+ allow(subject).to receive(:foo).and_raise(RuntimeError)
100
+ end
101
+ END
102
+ end
103
+
104
+ it 'converts into `allow(subject).to receive(:method).and_raise(RuntimeError)` form' do
105
+ method_stub_object.allowize!
106
+ rewritten_source.should == expected_source
107
+ end
108
+ end
109
+
110
+ context "when it's statement continues over multi lines" do
111
+ let(:source) do
112
+ <<-END
113
+ it 'responds to #foo' do
114
+ subject.#{method}(
115
+ :baz
116
+ ).
117
+ and_return(
118
+ 3
119
+ )
120
+ end
121
+ END
122
+ end
123
+
124
+ let(:expected_source) do
125
+ <<-END
126
+ it 'responds to #foo' do
127
+ allow(subject).to receive(
128
+ :baz
129
+ ).
130
+ and_return(
131
+ 3
132
+ )
133
+ end
134
+ END
135
+ end
136
+
137
+ it 'keeps the style as far as possible' do
138
+ method_stub_object.allowize!
139
+ rewritten_source.should == expected_source
140
+ end
141
+ end
142
+
143
+ context "when it is `subject.#{method}(:method => value)` form" do
144
+ let(:source) do
145
+ <<-END
146
+ it 'responds to #foo and returns 1' do
147
+ subject.#{method}(:foo => 1)
148
+ end
149
+ END
150
+ end
151
+
152
+ let(:expected_source) do
153
+ <<-END
154
+ it 'responds to #foo and returns 1' do
155
+ allow(subject).to receive(:foo).and_return(1)
156
+ end
157
+ END
158
+ end
159
+
160
+ it 'converts into `allow(subject).to receive(:method).and_return(value)` form' do
161
+ method_stub_object.allowize!
162
+ rewritten_source.should == expected_source
163
+ end
164
+ end
165
+
166
+ context "when it is `subject.#{method}(method: value)` form" do
167
+ let(:source) do
168
+ <<-END
169
+ it 'responds to #foo and returns 1' do
170
+ subject.#{method}(foo: 1)
171
+ end
172
+ END
173
+ end
174
+
175
+ let(:expected_source) do
176
+ <<-END
177
+ it 'responds to #foo and returns 1' do
178
+ allow(subject).to receive(:foo).and_return(1)
179
+ end
180
+ END
181
+ end
182
+
183
+ it 'converts into `allow(subject).to receive(:method).and_return(value)` form' do
184
+ method_stub_object.allowize!
185
+ rewritten_source.should == expected_source
186
+ end
187
+ end
188
+
189
+ context "when it is `subject.#{method}(:a_method => a_value, b_method => b_value)` form" do
190
+ let(:source) do
191
+ <<-END
192
+ it 'responds to #foo and returns 1' do
193
+ subject.#{method}(:foo => 1, :bar => 2)
194
+ end
195
+ END
196
+ end
197
+
198
+ let(:expected_source) do
199
+ <<-END
200
+ it 'responds to #foo and returns 1' do
201
+ allow(subject).to receive(:foo).and_return(1)
202
+ allow(subject).to receive(:bar).and_return(2)
203
+ end
204
+ END
205
+ end
206
+
207
+ it 'converts into `allow(subject).to receive(:a_method).and_return(a_value)` ' +
208
+ 'and `allow(subject).to receive(:b_method).and_return(b_value)` form' do
209
+ method_stub_object.allowize!
210
+ rewritten_source.should == expected_source
211
+ end
212
+
213
+ context "when it's statement continues over multi lines" do
214
+ let(:source) do
215
+ <<-END
216
+ it 'responds to #foo' do
217
+ subject
218
+ .#{method}(
219
+ :foo => 1,
220
+ :bar => 2
221
+ )
222
+ end
223
+ END
224
+ end
225
+
226
+ let(:expected_source) do
227
+ <<-END
228
+ it 'responds to #foo' do
229
+ allow(subject)
230
+ .to receive(:foo).and_return(1)
231
+ allow(subject)
232
+ .to receive(:bar).and_return(2)
233
+ end
234
+ END
235
+ end
236
+
237
+ it 'keeps the style except around the hash' do
238
+ method_stub_object.allowize!
239
+ rewritten_source.should == expected_source
240
+ end
241
+ end
242
+ end
243
+ end
244
+
245
+ [:unstub, :unstub!].each do |method|
246
+ context "when it is `subject.#{method}(:method)` form" do
247
+ let(:source) do
248
+ <<-END
249
+ it 'does not respond to #foo' do
250
+ subject.#{method}(:foo)
251
+ end
252
+ END
253
+ end
254
+
255
+ it 'does nothing' do
256
+ method_stub_object.allowize!
257
+ rewritten_source.should == source
258
+ end
259
+ end
260
+ end
261
+
262
+ [:stub, :stub!].each do |method|
263
+ context "when it is `SomeClass.any_instance.#{method}(:method)` form" do
264
+ let(:source) do
265
+ <<-END
266
+ it 'responds to #foo' do
267
+ SomeClass.any_instance.#{method}(:foo)
268
+ end
269
+ END
270
+ end
271
+
272
+ let(:expected_source) do
273
+ <<-END
274
+ it 'responds to #foo' do
275
+ allow_any_instance_of(SomeClass).to receive(:foo)
276
+ end
277
+ END
278
+ end
279
+
280
+ it 'converts into `allow_any_instance_of(SomeClass).to receive(:method)` form' do
281
+ method_stub_object.allowize!
282
+ rewritten_source.should == expected_source
283
+ end
284
+ end
285
+ end
286
+
287
+ [:unstub, :unstub!].each do |method|
288
+ context "when it is `SomeClass.any_instance.#{method}(:method)` form" do
289
+ let(:source) do
290
+ <<-END
291
+ it 'does not respond to #foo' do
292
+ SomeClass.any_instance.#{method}(:foo)
293
+ end
294
+ END
295
+ end
296
+
297
+ it 'does nothing' do
298
+ method_stub_object.allowize!
299
+ rewritten_source.should == source
300
+ end
301
+ end
302
+ end
303
+
304
+ context 'when already replaced deprecated method' do
305
+ let(:source) do
306
+ <<-END
307
+ it 'responds to #foo' do
308
+ subject.stub!(:foo)
309
+ end
310
+ END
311
+ end
312
+
313
+ it 'raises error' do
314
+ method_stub_object.replace_deprecated_method!
315
+ -> { method_stub_object.allowize! }.should raise_error
316
+ end
317
+ end
318
+ end
319
+
320
+ describe '#replace_deprecated_method!' do
321
+ [
322
+ [:stub!, :stub, 'responds to'],
323
+ [:unstub!, :unstub, 'does not respond to']
324
+ ].each do |method, replacement_method, description|
325
+ context "when it is ##{method}" do
326
+ let(:source) do
327
+ <<-END
328
+ it '#{description} #foo' do
329
+ subject.#{method}(:foo)
330
+ end
331
+ END
332
+ end
333
+
334
+ let(:expected_source) do
335
+ <<-END
336
+ it '#{description} #foo' do
337
+ subject.#{replacement_method}(:foo)
338
+ end
339
+ END
340
+ end
341
+
342
+ it "replaces with ##{replacement_method}" do
343
+ method_stub_object.replace_deprecated_method!
344
+ rewritten_source.should == expected_source
345
+ end
346
+ end
347
+ end
348
+
349
+ [
350
+ [:stub, 'responds to'],
351
+ [:unstub, 'does not respond to']
352
+ ].each do |method, description|
353
+ context "when it is ##{method}" do
354
+ let(:source) do
355
+ <<-END
356
+ it '#{description} #foo' do
357
+ subject.#{method}(:foo)
358
+ end
359
+ END
360
+ end
361
+
362
+ it 'does nothing' do
363
+ method_stub_object.replace_deprecated_method!
364
+ rewritten_source.should == source
365
+ end
366
+ end
367
+ end
368
+
369
+ context 'when already allowized' do
370
+ let(:source) do
371
+ <<-END
372
+ it 'responds to #foo' do
373
+ subject.stub!(:foo)
374
+ end
375
+ END
376
+ end
377
+
378
+ it 'raises error' do
379
+ method_stub_object.allowize!
380
+ -> { method_stub_object.replace_deprecated_method! }.should raise_error
381
+ end
382
+ end
383
+ end
384
+ end
385
+ end
386
+ end
@@ -0,0 +1,286 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module Transpec
6
+ class Syntax
7
+ describe ShouldReceive do
8
+ include_context 'parsed objects'
9
+
10
+ subject(:should_receive_object) do
11
+ AST::Scanner.scan(ast) do |node, ancestor_nodes, in_example_group_context|
12
+ next unless ShouldReceive.target_node?(node)
13
+ return ShouldReceive.new(
14
+ node,
15
+ ancestor_nodes,
16
+ in_example_group_context?,
17
+ source_rewriter
18
+ )
19
+ end
20
+ fail 'No should_receive node is found!'
21
+ end
22
+
23
+ let(:in_example_group_context?) { true }
24
+
25
+ describe '#expectize!' do
26
+ context 'when it is `subject.should_receive(:method)` form' do
27
+ let(:source) do
28
+ <<-END
29
+ it 'receives #foo' do
30
+ subject.should_receive(:foo)
31
+ end
32
+ END
33
+ end
34
+
35
+ let(:expected_source) do
36
+ <<-END
37
+ it 'receives #foo' do
38
+ expect(subject).to receive(:foo)
39
+ end
40
+ END
41
+ end
42
+
43
+ it 'converts into `expect(subject).to receive(:method)` form' do
44
+ should_receive_object.expectize!
45
+ rewritten_source.should == expected_source
46
+ end
47
+ end
48
+
49
+ context 'when it is `subject.should_not_receive(:method)` form' do
50
+ let(:source) do
51
+ <<-END
52
+ it 'does not receive #foo' do
53
+ subject.should_not_receive(:foo)
54
+ end
55
+ END
56
+ end
57
+
58
+ let(:expected_source) do
59
+ <<-END
60
+ it 'does not receive #foo' do
61
+ expect(subject).not_to receive(:foo)
62
+ end
63
+ END
64
+ end
65
+
66
+ it 'converts into `expect(subject).not_to receive(:method)` form' do
67
+ should_receive_object.expectize!
68
+ rewritten_source.should == expected_source
69
+ end
70
+
71
+ context 'and "to_not" is passed as negative form' do
72
+ let(:expected_source) do
73
+ <<-END
74
+ it 'does not receive #foo' do
75
+ expect(subject).to_not receive(:foo)
76
+ end
77
+ END
78
+ end
79
+
80
+ it 'converts into `expect(subject).to_not receive(:method)` form' do
81
+ should_receive_object.expectize!('to_not')
82
+ rewritten_source.should == expected_source
83
+ end
84
+ end
85
+ end
86
+
87
+ # Currently MessageExpectation#with supports the following syntax:
88
+ #
89
+ # subject.should_receive(:foo).with do |arg|
90
+ # arg == 1
91
+ # end
92
+ #
93
+ # This syntax allows to expect arbitrary arguments without expect or should.
94
+ # This is available only when #with got no normal arguments but a block,
95
+ # and the block will not be used as a substitute implementation.
96
+ #
97
+ # https://github.com/rspec/rspec-mocks/blob/e6d1980/lib/rspec/mocks/message_expectation.rb#L307
98
+ # https://github.com/rspec/rspec-mocks/blob/e6d1980/lib/rspec/mocks/argument_list_matcher.rb#L43
99
+ #
100
+ # Then, if you convert the example into expect syntax straightforward:
101
+ #
102
+ # expect(subject).to receive(:foo).with do |arg|
103
+ # arg == 1
104
+ # end
105
+ #
106
+ # The do..end block is taken by the #to method, because {..} blocks have higher precedence
107
+ # over do..end blocks. This behavior breaks the spec.
108
+ #
109
+ # To keep the same meaning of syntax, the block needs to be {..} form literal:
110
+ #
111
+ # expect(subject).to receive(:foo).with { |arg|
112
+ # arg == 1
113
+ # }
114
+ #
115
+ context 'when it is `subject.should_receive(:method).with do..end` form' do
116
+ let(:source) do
117
+ <<-END
118
+ it 'receives #foo with 1' do
119
+ subject.should_receive(:foo).with do |arg|
120
+ arg == 1
121
+ end
122
+ subject.foo(1)
123
+ end
124
+ END
125
+ end
126
+
127
+ let(:expected_source) do
128
+ <<-END
129
+ it 'receives #foo with 1' do
130
+ expect(subject).to receive(:foo).with { |arg|
131
+ arg == 1
132
+ }
133
+ subject.foo(1)
134
+ end
135
+ END
136
+ end
137
+
138
+ it 'converts into `expect(subject).to receive(:method) { .. }` form' do
139
+ should_receive_object.expectize!
140
+ rewritten_source.should == expected_source
141
+ end
142
+ end
143
+
144
+ # If #with take normal arguments, the block won't be used as an argument matcher.
145
+ context 'when it is `subject.should_receive(:method).with(:arg) do..end` form' do
146
+ let(:source) do
147
+ <<-END
148
+ it 'receives #foo with 1' do
149
+ subject.should_receive(:foo).with(:bar) do |arg|
150
+ do_some_substitute_implementation
151
+ end
152
+ subject.foo(1)
153
+ end
154
+ END
155
+ end
156
+
157
+ let(:expected_source) do
158
+ <<-END
159
+ it 'receives #foo with 1' do
160
+ expect(subject).to receive(:foo).with(:bar) do |arg|
161
+ do_some_substitute_implementation
162
+ end
163
+ subject.foo(1)
164
+ end
165
+ END
166
+ end
167
+
168
+ it 'converts into `expect(subject).to receive(:method) { .. }` form' do
169
+ should_receive_object.expectize!
170
+ rewritten_source.should == expected_source
171
+ end
172
+ end
173
+
174
+ # In this case, the do..end block is taken by the #should_receive method.
175
+ # This means the receiver of #once method is return value of #should_receive,
176
+ # that is actually an instance of RSpec::Mocks::MessageExpectation.
177
+ #
178
+ # subject.should_receive(:foo) do |arg|
179
+ # arg == 1
180
+ # end.once
181
+ #
182
+ # However with `expect(subject).to receive`, the do..end block is taken by the #to method.
183
+ # This means the receiver of #once method is return value of #to, that is actually
184
+ # return value of RSpec::Mocks::Matchers::Receive#setup_method_substitute
185
+ # and it's not the instance of RSpec::Mocks::MessageExpectation.
186
+ #
187
+ # https://github.com/rspec/rspec-mocks/blob/9cdef17/lib/rspec/mocks/targets.rb#L19
188
+ # https://github.com/rspec/rspec-mocks/blob/9cdef17/lib/rspec/mocks/matchers/receive.rb#L74
189
+ #
190
+ # Then, the following syntax will be error:
191
+ #
192
+ # expect(subject).to receive(:foo) do |arg|
193
+ # arg == 1
194
+ # end.once
195
+ #
196
+ # So the block needs to be {..} form literal also in this case.
197
+ #
198
+ # expect(subject).to receive(:foo) { |arg|
199
+ # arg == 1
200
+ # }.once
201
+ #
202
+ context 'when it is `subject.should_receive(:method) do..end.once` form' do
203
+ let(:source) do
204
+ <<-END
205
+ it 'receives #foo with 1' do
206
+ subject.should_receive(:foo) do |arg|
207
+ arg == 1
208
+ end.once
209
+ subject.foo(1)
210
+ end
211
+ END
212
+ end
213
+
214
+ let(:expected_source) do
215
+ <<-END
216
+ it 'receives #foo with 1' do
217
+ expect(subject).to receive(:foo) { |arg|
218
+ arg == 1
219
+ }.once
220
+ subject.foo(1)
221
+ end
222
+ END
223
+ end
224
+
225
+ it 'converts into `expect(subject).to receive(:method) { .. }.once` form' do
226
+ should_receive_object.expectize!
227
+ rewritten_source.should == expected_source
228
+ end
229
+ end
230
+
231
+ # This case, do..end block works without problem.
232
+ context 'when it is `subject.should_receive(:method) do..end` form' do
233
+ let(:source) do
234
+ <<-END
235
+ it 'receives #foo with 1' do
236
+ subject.should_receive(:foo) do |arg|
237
+ expect(arg).to eq(1)
238
+ end
239
+ subject.foo(1)
240
+ end
241
+ END
242
+ end
243
+
244
+ let(:expected_source) do
245
+ <<-END
246
+ it 'receives #foo with 1' do
247
+ expect(subject).to receive(:foo) do |arg|
248
+ expect(arg).to eq(1)
249
+ end
250
+ subject.foo(1)
251
+ end
252
+ END
253
+ end
254
+
255
+ it 'converts into `expect(subject).to receive(:method) do..end` form' do
256
+ should_receive_object.expectize!
257
+ rewritten_source.should == expected_source
258
+ end
259
+ end
260
+
261
+ context 'when it is `SomeClass.any_instance.should_receive(:method)` form' do
262
+ let(:source) do
263
+ <<-END
264
+ it 'receives #foo' do
265
+ SomeClass.any_instance.should_receive(:foo)
266
+ end
267
+ END
268
+ end
269
+
270
+ let(:expected_source) do
271
+ <<-END
272
+ it 'receives #foo' do
273
+ expect_any_instance_of(SomeClass).to receive(:foo)
274
+ end
275
+ END
276
+ end
277
+
278
+ it 'converts into `expect_any_instance_of(SomeClass).to receive(:method)` form' do
279
+ should_receive_object.expectize!
280
+ rewritten_source.should == expected_source
281
+ end
282
+ end
283
+ end
284
+ end
285
+ end
286
+ end