minitest_to_rspec 0.11.0 → 0.12.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 (36) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +3 -2
  3. data/CHANGELOG.md +19 -0
  4. data/README.md +3 -0
  5. data/lib/minitest_to_rspec/converter.rb +2 -2
  6. data/lib/minitest_to_rspec/input/model/base.rb +15 -0
  7. data/lib/minitest_to_rspec/input/model/call.rb +185 -0
  8. data/lib/minitest_to_rspec/input/model/defn.rb +37 -0
  9. data/lib/minitest_to_rspec/input/model/hash_exp.rb +24 -0
  10. data/lib/minitest_to_rspec/input/model/iter.rb +89 -0
  11. data/lib/minitest_to_rspec/input/model/klass.rb +102 -0
  12. data/lib/minitest_to_rspec/input/processor.rb +40 -0
  13. data/lib/minitest_to_rspec/input/subprocessors/base.rb +91 -0
  14. data/lib/minitest_to_rspec/input/subprocessors/call.rb +279 -0
  15. data/lib/minitest_to_rspec/input/subprocessors/defn.rb +64 -0
  16. data/lib/minitest_to_rspec/input/subprocessors/iter.rb +148 -0
  17. data/lib/minitest_to_rspec/input/subprocessors/klass.rb +101 -0
  18. data/lib/minitest_to_rspec/minitest/stub.rb +85 -0
  19. data/lib/minitest_to_rspec/{expression_builders → rspec}/stub.rb +3 -2
  20. data/lib/minitest_to_rspec/type.rb +1 -1
  21. data/lib/minitest_to_rspec/version.rb +1 -1
  22. metadata +17 -18
  23. data/lib/minitest_to_rspec/model/base.rb +0 -13
  24. data/lib/minitest_to_rspec/model/call.rb +0 -165
  25. data/lib/minitest_to_rspec/model/calls/once.rb +0 -13
  26. data/lib/minitest_to_rspec/model/calls/twice.rb +0 -13
  27. data/lib/minitest_to_rspec/model/defn.rb +0 -27
  28. data/lib/minitest_to_rspec/model/hash_exp.rb +0 -20
  29. data/lib/minitest_to_rspec/model/iter.rb +0 -79
  30. data/lib/minitest_to_rspec/model/klass.rb +0 -100
  31. data/lib/minitest_to_rspec/processor.rb +0 -38
  32. data/lib/minitest_to_rspec/subprocessors/base.rb +0 -89
  33. data/lib/minitest_to_rspec/subprocessors/call.rb +0 -391
  34. data/lib/minitest_to_rspec/subprocessors/defn.rb +0 -49
  35. data/lib/minitest_to_rspec/subprocessors/iter.rb +0 -138
  36. data/lib/minitest_to_rspec/subprocessors/klass.rb +0 -99
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../call'
4
- require_relative '../../errors'
5
-
6
- module MinitestToRspec
7
- module Model
8
- module Calls
9
- class Once < Call
10
- end
11
- end
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../call'
4
- require_relative '../../errors'
5
-
6
- module MinitestToRspec
7
- module Model
8
- module Calls
9
- class Twice < Call
10
- end
11
- end
12
- end
13
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module MinitestToRspec
6
- module Model
7
- # Data object. Represents a `:defn` s-expression.
8
- class Defn < Base
9
- def initialize(exp)
10
- assert_sexp_type(:defn, exp)
11
- @exp = exp.dup
12
- end
13
-
14
- def body
15
- @exp[3..-1]
16
- end
17
-
18
- def method_name
19
- @exp[1].to_s
20
- end
21
-
22
- def test_method?
23
- method_name.start_with?('test_')
24
- end
25
- end
26
- end
27
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module MinitestToRspec
4
- module Model
5
- # Data object. Represents a `:hash` S-expression.
6
- class HashExp < Base
7
- def initialize(sexp)
8
- assert_sexp_type(:hash, sexp)
9
- @exp = sexp.dup
10
- end
11
-
12
- # A slightly nicer implementation would be:
13
- # `@exp[1..-1].each_slice(2).to_h`
14
- # but that would require ruby >= 2.1
15
- def to_h
16
- Hash[@exp[1..-1].each_slice(2).to_a]
17
- end
18
- end
19
- end
20
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module MinitestToRspec
6
- module Model
7
- # Data object. Represents an `:iter` s-expression.
8
- class Iter < Base
9
- def initialize(exp)
10
- assert_sexp_type(:iter, exp)
11
- @exp = exp.dup
12
- end
13
-
14
- def [](*args)
15
- @exp[*args]
16
- end
17
-
18
- def assert_difference?
19
- !empty? && Model::Call.assert_difference?(@exp[1])
20
- end
21
-
22
- def assert_no_difference?
23
- !empty? && Model::Call.assert_no_difference?(@exp[1])
24
- end
25
-
26
- def assert_nothing_raised?
27
- !empty? && Model::Call.assert_nothing_raised?(@exp[1])
28
- end
29
-
30
- def assert_raise?
31
- !empty? && Model::Call.assert_raise?(@exp[1])
32
- end
33
-
34
- def assert_raises?
35
- !empty? && Model::Call.assert_raises?(@exp[1])
36
- end
37
-
38
- def block
39
- @exp[3]
40
- end
41
-
42
- def call
43
- @exp[1]
44
- end
45
-
46
- # Not to be confused with block arguments.
47
- def call_arguments
48
- call_obj.arguments
49
- end
50
-
51
- def call_obj
52
- Model::Call.new(call)
53
- end
54
-
55
- # Enumerates children, skipping the base `call` and
56
- # starting with the block arguments, then each `:call` in
57
- # the block.
58
- def each
59
- @exp[2..-1].each do |e| yield(e) end
60
- end
61
-
62
- def empty?
63
- @exp.length == 1 # just the sexp_type
64
- end
65
-
66
- def setup?
67
- !empty? && Model::Call.method_name?(@exp[1], :setup)
68
- end
69
-
70
- def teardown?
71
- !empty? && Model::Call.method_name?(@exp[1], :teardown)
72
- end
73
-
74
- def sexp
75
- @exp
76
- end
77
- end
78
- end
79
- end
@@ -1,100 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'base'
4
-
5
- module MinitestToRspec
6
- module Model
7
- # Data object. Represents a `:class` S-expression.
8
- class Klass < Base
9
- def initialize(exp)
10
- assert_sexp_type(:class, exp)
11
- @exp = exp.dup
12
- assert_valid_name
13
- end
14
-
15
- def action_controller_test_case?
16
- lineage?(parent, %i[ActionController TestCase])
17
- end
18
-
19
- def action_mailer_test_case?
20
- lineage?(parent, %i[ActionMailer TestCase])
21
- end
22
-
23
- def active_support_test_case?
24
- lineage?(parent, %i[ActiveSupport TestCase])
25
- end
26
-
27
- # Raise an error if we don't know now to process the name
28
- # of this class. Specifically, classes with module-shorthand.
29
- def assert_valid_name
30
- if name.is_a?(Symbol)
31
- # Valid
32
- elsif name.respond_to?(:sexp_type) && name.sexp_type == :colon2
33
- raise ModuleShorthandError
34
- else
35
- raise ProcessingError, "Unexpected class expression: #{name}"
36
- end
37
- end
38
-
39
- def block?
40
- !block.empty?
41
- end
42
-
43
- def block
44
- @_block ||= @exp[3..-1] || []
45
- end
46
-
47
- def draper_test_case?
48
- lineage?(parent, %i[Draper TestCase])
49
- end
50
-
51
- # Returns the name of the class. Examples:
52
- #
53
- # - Banana #=> :Banana
54
- # - Fruit::Banana #=> s(:colon2, s(:const, :Fruit), :Banana)
55
- #
56
- # Note that the latter (module shorthand) is not supported
57
- # by MinitestToRspec. See `#assert_valid_name`.
58
- #
59
- def name
60
- @exp[1]
61
- end
62
-
63
- # Returns the "inheritance". Examples:
64
- #
65
- # - Inherit nothing #=> nil
66
- # - Inherit Foo #=> s(:const, :Foo)
67
- # - Inherit Bar::Foo #=> s(:colon2, s(:const, :Bar), :Foo)
68
- #
69
- def parent
70
- @_parent ||= @exp[2]
71
- end
72
-
73
- # Returns true if `@exp` inherits from, e.g. ActiveSupport::TestCase.
74
- # TODO: Other test case parent classes.
75
- def test_case?
76
- return false unless sexp_type?(:colon2, parent)
77
- active_support_test_case? ||
78
- action_controller_test_case? ||
79
- action_mailer_test_case? ||
80
- draper_test_case?
81
- end
82
-
83
- private
84
-
85
- def ancestor_name(exp, index)
86
- assert_sexp_type(:colon2, exp)
87
- ancestor = exp[index + 1]
88
- sexp_type?(:const, ancestor) ? ancestor[1] : ancestor
89
- end
90
-
91
- def lineage?(exp, names)
92
- assert_sexp_type(:colon2, exp)
93
- exp.length == names.length + 1 &&
94
- names.each_with_index.all? { |name, ix|
95
- name.to_sym == ancestor_name(exp, ix).to_sym
96
- }
97
- end
98
- end
99
- end
100
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'ruby_parser'
4
- require 'sexp_processor'
5
- require_relative 'subprocessors/call'
6
- require_relative 'subprocessors/defn'
7
- require_relative 'subprocessors/klass'
8
- require_relative 'subprocessors/iter'
9
-
10
- module MinitestToRspec
11
- # Consumes a `String` of minitest code and returns an S-expression
12
- # representing equivalent RSpec code. The main method is `#process`. See
13
- # `SexpProcessor` docs for details.
14
- class Processor < SexpProcessor
15
- def initialize(rails, mocha)
16
- super()
17
- self.strict = false
18
- @mocha = mocha
19
- @rails = rails
20
- end
21
-
22
- def process_call(exp)
23
- Subprocessors::Call.new(exp, @rails, @mocha).process
24
- end
25
-
26
- def process_class(exp)
27
- Subprocessors::Klass.new(exp, @rails, @mocha).process
28
- end
29
-
30
- def process_defn(exp)
31
- Subprocessors::Defn.new(exp, @rails, @mocha).process
32
- end
33
-
34
- def process_iter(exp)
35
- Subprocessors::Iter.new(exp, @rails, @mocha).process
36
- end
37
- end
38
- end
@@ -1,89 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../sexp_assertions'
4
-
5
- module MinitestToRspec
6
- module Subprocessors
7
- # Parent class of "sub-processors". There is one sub-processor for each
8
- # `sexp_type` that `Processor` knows how to process.
9
- #
10
- # For example, `Subprocessors::Call` will process an `s(:call, ..)`
11
- # expression representing minitest code, and return an S-expression
12
- # representing equivalent RSpec code.
13
- class Base
14
- include SexpAssertions
15
-
16
- def initialize(rails, mocha)
17
- @rails = rails
18
- @mocha = mocha
19
- end
20
-
21
- # Returns a s-expression representing an rspec-mocks stub.
22
- def allow_to(msg_recipient, matcher, any_instance = false)
23
- allow_method = any_instance ? :allow_any_instance_of : :allow
24
- target = s(:call, nil, allow_method, msg_recipient)
25
- s(:call, target, :to, matcher)
26
- end
27
-
28
- # Returns a s-expression representing an RSpec expectation, i.e. the
29
- # combination of an "expectation target" and a matcher.
30
- def expect(target, eager, phase, matcher, any_instance)
31
- et = expectation_target(target, eager, any_instance)
32
- s(:call, et, phase, matcher)
33
- end
34
-
35
- def expect_to(matcher, target, eager, any_instance = false)
36
- expect(target, eager, :to, matcher, any_instance)
37
- end
38
-
39
- def expect_to_not(matcher, target, eager)
40
- expect(target, eager, :to_not, matcher, false)
41
- end
42
-
43
- # In RSpec, `expect` returns an "expectation target". This
44
- # can be based on an expression, as in `expect(1 + 1)` or it
45
- # can be based on a block, as in `expect { raise }`. Either
46
- # way, it's called an "expectation target".
47
- def expectation_target(exp, eager, any_instance)
48
- if eager
49
- expectation_target_eager(exp, any_instance)
50
- else
51
- expectation_target_lazy(exp)
52
- end
53
- end
54
-
55
- def expectation_target_eager(exp, any_instance)
56
- expect_method = any_instance ? :expect_any_instance_of : :expect
57
- s(:call, nil, expect_method, exp)
58
- end
59
-
60
- def expectation_target_lazy(block)
61
- s(:iter,
62
- s(:call, nil, :expect),
63
- 0,
64
- full_process(block)
65
- )
66
- end
67
-
68
- # If it's a `Sexp`, run `obj` through a new `Processor`. Otherwise,
69
- # return `obj`.
70
- #
71
- # This is useful for expressions that cannot be fully understood by a
72
- # single subprocessor. For example, we must begin processing all :iter
73
- # expressions, because some :iter represent calls we're interested in,
74
- # e.g. `assert_difference`. However, if the :iter turns out to be
75
- # uninteresting (perhaps it has no assertions) we still want to fully
76
- # process its sub-expressions.
77
- #
78
- # TODO: `full_process` may not be the best name.
79
- def full_process(obj)
80
- obj.is_a?(Sexp) ? Processor.new(@rails, @mocha).process(obj) : obj
81
- end
82
-
83
- def matcher(name, *args)
84
- exp = s(:call, nil, name)
85
- exp.concat(args)
86
- end
87
- end
88
- end
89
- end
@@ -1,391 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'minitest_to_rspec/type'
4
- require 'minitest_to_rspec/expression_builders/stub'
5
- require_relative '../model/call'
6
- require_relative '../model/hash_exp'
7
- require_relative 'base'
8
-
9
- module MinitestToRspec
10
- module Subprocessors
11
- # Processes `s(:call, ..)` expressions.
12
- class Call < Base
13
- # Mocha methods will only be processed if `--mocha` flag was given,
14
- # i.e. `mocha` argument in constructor is true.
15
- MOCHA_METHODS = %i[
16
- expects
17
- once
18
- returns
19
- stub
20
- stubs
21
- stub_everything
22
- twice
23
- ].freeze
24
-
25
- def initialize(sexp, rails, mocha)
26
- super(rails, mocha)
27
- @exp = Model::Call.new(sexp)
28
- sexp.clear
29
- end
30
-
31
- # Given a `Model::Call`, returns a `Sexp`
32
- def process
33
- if process?
34
- send(name_of_processing_method)
35
- else
36
- @exp.original
37
- end
38
- end
39
-
40
- def process?
41
- respond_to?(name_of_processing_method, true) &&
42
- (@mocha || !MOCHA_METHODS.include?(@exp.method_name))
43
- end
44
-
45
- private
46
-
47
- # - msg_rcp. Message recipient. The object to be stubbed.
48
- # - msg. Message. The name of the stubbed method.
49
- # - ret_vals. Return values.
50
- # - any_ins. Any instance? True if this is an `any_instance` stub.
51
- # - with. Allowed arguments.
52
- def allow_receive_and_return(msg_rcp, msg, ret_vals, any_ins, with)
53
- allow_to(
54
- msg_rcp,
55
- receive_and_return(msg, ret_vals, with),
56
- any_ins
57
- )
58
- end
59
-
60
- # Given `exp`, an S-expression representing an rspec-mocks statement
61
- # (expect or allow) apply `ordinal`, which is either `:once` or `:twice`.
62
- # This feels like a hack. No other processing "re-opens" an "output
63
- # sexp".
64
- def apply_expectation_count_to(exp, ordinal)
65
- exp[3] = s(:call, exp[3], ordinal)
66
- exp
67
- end
68
-
69
- def be_falsey
70
- matcher(:be_falsey)
71
- end
72
-
73
- def be_nil
74
- matcher(:be_nil)
75
- end
76
-
77
- def be_truthy
78
- matcher(:be_truthy)
79
- end
80
-
81
- def call_to_question_mark?(exp)
82
- sexp_type?(:call, exp) && Model::Call.new(exp).question_mark_method?
83
- end
84
-
85
- def eq(exp)
86
- matcher(:eq, exp)
87
- end
88
-
89
- # - msg_rcp. Message recipient. The object to be stubbed.
90
- # - msg. Message. The name of the stubbed method.
91
- # - ret_vals. Return values.
92
- # - any_ins. Any instance? True if this is an `any_instance` stub.
93
- # - with. Allowed arguments.
94
- def expect_receive_and_return(msg_rcp, msg, ret_vals, any_ins, with)
95
- expect_to(
96
- receive_and_return(msg, ret_vals, with),
97
- msg_rcp,
98
- true,
99
- any_ins
100
- )
101
- end
102
-
103
- # Given a `Sexp` representing a `Hash` of message expectations,
104
- # return an array of `Sexp`, each representing an expectation
105
- # in rspec-mocks syntax.
106
- def hash_to_expectations(sexp, receiver)
107
- Model::HashExp.new(sexp).to_h.map { |msg, ret_val|
108
- expect_receive_and_return(
109
- receiver.deep_clone, msg, wrap_sexp(ret_val), false, []
110
- )
111
- }
112
- end
113
-
114
- def match(pattern)
115
- matcher(:match, pattern)
116
- end
117
-
118
- def method_assert
119
- refsert eq(s(:true)), be_truthy
120
- end
121
-
122
- def method_assert_equal
123
- expected = @exp.arguments[0]
124
- calculated = @exp.arguments[1]
125
- expect_to(eq(expected), calculated, true)
126
- end
127
-
128
- def method_assert_match
129
- pattern = @exp.arguments[0]
130
- string = @exp.arguments[1]
131
- expect_to(match(pattern), string, true)
132
- end
133
-
134
- def method_assert_nil
135
- expect_to(be_nil, @exp.arguments[0], true)
136
- end
137
-
138
- def method_assert_not_nil
139
- expect_to_not(be_nil, @exp.arguments[0], true)
140
- end
141
-
142
- def method_assert_not_equal
143
- expected = @exp.arguments[0]
144
- calculated = @exp.arguments[1]
145
- expect_to_not(eq(expected), calculated, true)
146
- end
147
-
148
- def method_expects
149
- if @exp.num_arguments == 1
150
- mocha_expects(@exp)
151
- else
152
- @exp.original
153
- end
154
- end
155
-
156
- def method_once
157
- mocha_once(@exp)
158
- end
159
-
160
- def method_refute
161
- refsert eq(s(:false)), be_falsey
162
- end
163
-
164
- def method_refute_equal
165
- unexpected = @exp.arguments[0]
166
- calculated = @exp.arguments[1]
167
- expect_to_not(eq(unexpected), calculated, true)
168
- end
169
-
170
- # Processes an entire line of code that ends in `.returns`
171
- def method_returns
172
- receiver = mocha_stub_receiver(@exp)
173
- any_instance = rspec_any_instance?(@exp)
174
- message_call = mocha_stub_expects(@exp)
175
- message = message_call.arguments.first
176
- with = mocha_stub_with(@exp)
177
- returns = @exp.arguments.first
178
- count = message_call.method_name == :expects ? 1 : nil
179
- ExpressionBuilders::Stub.new(
180
- receiver, any_instance, message, with, returns, count
181
- ).to_rspec_exp
182
- rescue StandardError
183
- # TODO: We used to have an `UnknownVariant` error.
184
- # That was nice and specific.
185
- @exp.original
186
- end
187
-
188
- def method_require
189
- if @exp.require_test_helper?
190
- require_spec_helper
191
- else
192
- @exp.original
193
- end
194
- end
195
-
196
- def method_should
197
- s(:call, nil, :it, *@exp.arguments)
198
- end
199
-
200
- # Happily, the no-block signatures of [stub][3] are the
201
- # same as [double][2].
202
- #
203
- # - (name)
204
- # - (stubs)
205
- # - (name, stubs)
206
-
207
- def method_stub
208
- mocha_stub(@exp)
209
- end
210
-
211
- # [stub_everything][1] responds to all messages with nil.
212
- # [double.as_null_object][4] responds with self. Not a
213
- # drop-in replacement, but will work in many situations.
214
- # RSpec doesn't provide an equivalent to `stub_everything`,
215
- # AFAIK.
216
-
217
- def method_stub_everything
218
- if @exp.receiver.nil?
219
- d = s(:call, nil, :double, *@exp.arguments)
220
- s(:call, d, :as_null_object)
221
- else
222
- @exp.original
223
- end
224
- end
225
-
226
- def method_test
227
- s(:call, nil, :it, *@exp.arguments)
228
- end
229
-
230
- def method_twice
231
- mocha_twice(@exp)
232
- end
233
-
234
- def mocha_expects(exp)
235
- raise ArgumentError unless exp.is_a?(Model::Call)
236
- arg = exp.arguments.first
237
- if sexp_type?(:hash, arg)
238
- mocha_expects_hash(exp, arg)
239
- elsif sexp_type?(:lit, arg)
240
- mocha_expects_lit(exp, arg)
241
- else
242
- exp.original
243
- end
244
- end
245
-
246
- def mocha_expects_hash(exp, hash_sexp)
247
- assert_sexp_type(:hash, hash_sexp)
248
- pointless_lambda(hash_to_expectations(hash_sexp, exp.receiver))
249
- end
250
-
251
- def mocha_expects_lit(exp, lit_sexp)
252
- assert_sexp_type(:lit, lit_sexp)
253
- expect_to(receive_and_call_original(lit_sexp), exp.receiver, true)
254
- end
255
-
256
- # TODO: add support for
257
- # - at_least
258
- # - at_least_once
259
- # - at_most
260
- # - at_most_once
261
- # - never
262
- def mocha_expectation_count(exp, count)
263
- Type.assert(Model::Call, exp)
264
- Type.assert(Integer, count)
265
- receiver = mocha_stub_receiver(exp)
266
- any_instance = rspec_any_instance?(exp)
267
- message = mocha_stub_expects(exp).arguments.first
268
- with = mocha_stub_with(exp)
269
- returns = exp.find_call_in_receiver_chain(:returns)&.arguments&.first
270
- ExpressionBuilders::Stub.new(
271
- receiver, any_instance, message, with, returns, count
272
- ).to_rspec_exp
273
- end
274
-
275
- # Given a mocha stub, e.g. `X.any_instance.expects(:y)`, returns `X`.
276
- def mocha_stub_receiver(exp)
277
- chain = exp.receiver_chain
278
- last = chain[-1]
279
- last.nil? ? chain[-2] : last
280
- end
281
-
282
- # Given an `exp` representing a chain of calls, like
283
- # `stubs(x).returns(y).once`, finds the call to `stubs` or `expects`.
284
- def mocha_stub_expects(exp)
285
- exp.find_call_in_receiver_chain(%i[stubs expects])
286
- end
287
-
288
- def mocha_stub_with(exp)
289
- exp.find_call_in_receiver_chain(:with)&.arguments&.first
290
- end
291
-
292
- def rspec_any_instance?(exp)
293
- exp.calls_in_receiver_chain.any? { |i|
294
- i.method_name.to_s.include?('any_instance')
295
- }
296
- end
297
-
298
- def mocha_once(exp)
299
- mocha_expectation_count(exp, 1)
300
- end
301
-
302
- def mocha_stub(exp)
303
- raise ArgumentError unless exp.is_a?(Model::Call)
304
- if exp.receiver.nil?
305
- s(:call, nil, :double, *exp.arguments)
306
- else
307
- exp.original
308
- end
309
- end
310
-
311
- def mocha_twice(exp)
312
- mocha_expectation_count(exp, 2)
313
- end
314
-
315
- def name_of_processing_method
316
- "method_#{@exp.method_name}".to_sym
317
- end
318
-
319
- # Given `array_of_calls`, returns a `Sexp` representing a
320
- # self-executing lambda.
321
- #
322
- # This works around the fact that `sexp_processor` expects us to return
323
- # a single `Sexp`, not an array of `Sexp`. We also can't return a
324
- # `:block`, or else certain input would produce nested blocks (e.g.
325
- # `s(:block, s(:block, ..))`) which `ruby2ruby` (naturally) does not know
326
- # how to process. So, the easiest solution I could think of is a
327
- # self-executing lambda.
328
- #
329
- # Currently, the only `:call` which we process into multiple calls is
330
- # the hash form of a mocha `#expects`, thankfully uncommon.
331
- #
332
- # To get better output (without a pointless lambda) we would have to
333
- # process `:block` *and* `:defn`, which we are not yet doing.
334
-
335
- def pointless_lambda(array_of_calls)
336
- assert_sexp_type_array(:call, array_of_calls)
337
- s(:call,
338
- s(:iter,
339
- s(:call, nil, :lambda),
340
- 0,
341
- s(:block,
342
- s(:str, 'Sorry for the pointless lambda here.'),
343
- *array_of_calls
344
- )
345
- ),
346
- :call
347
- )
348
- end
349
-
350
- def receive(message, with = [])
351
- r = s(:call, nil, :receive, message)
352
- if with.empty?
353
- r
354
- else
355
- s(:call, r, :with, *with)
356
- end
357
- end
358
-
359
- def receive_and_call_original(message)
360
- s(:call, s(:call, nil, :receive, message), :and_call_original)
361
- end
362
-
363
- def receive_and_return(message, return_values, with = [])
364
- s(:call, receive(message, with), :and_return, *return_values)
365
- end
366
-
367
- # `refsert` - Code shared by refute and assert. I could also have gone
368
- # with `assfute`. Wooo .. time for bed.
369
- def refsert(exact, fuzzy)
370
- actual = @exp.arguments[0]
371
- matcher = call_to_question_mark?(actual) ? exact : fuzzy
372
- expect_to(matcher, actual, true)
373
- end
374
-
375
- def require_spec_helper
376
- prefix = @rails ? 'rails' : 'spec'
377
- s(:call, nil, :require, s(:str, "#{prefix}_helper"))
378
- end
379
-
380
- # Wraps `obj` in an `Array` if it is a `Sexp`
381
- def wrap_sexp(obj)
382
- obj.is_a?(Sexp) ? [obj] : obj
383
- end
384
- end
385
- end
386
- end
387
-
388
- # [1]: http://bit.ly/1yll6ND
389
- # [2]: http://bit.ly/1CRdmP3
390
- # [3]: http://bit.ly/1aY2mJN
391
- # [4]: http://bit.ly/1OtwDOY