transpec 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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