interactor-strict 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.
- checksums.yaml +7 -0
- data/.github/workflows/tests.yml +35 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/.standard.yml +4 -0
- data/CHANGELOG.md +53 -0
- data/CONTRIBUTING.md +39 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +48 -0
- data/README.md +64 -0
- data/Rakefile +7 -0
- data/interactor-strict.gemspec +20 -0
- data/lib/interactor/strict.rb +40 -0
- data/spec/integration_spec.rb +1777 -0
- data/spec/interactor/context_spec.rb +201 -0
- data/spec/interactor/hooks_spec.rb +358 -0
- data/spec/interactor/organizer_spec.rb +57 -0
- data/spec/interactor/strict_spec.rb +95 -0
- data/spec/interactor_spec.rb +3 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/lint.rb +144 -0
- metadata +112 -0
@@ -0,0 +1,201 @@
|
|
1
|
+
module Interactor
|
2
|
+
describe Context do
|
3
|
+
describe ".build" do
|
4
|
+
it "converts the given hash to a context" do
|
5
|
+
context = Context.build(foo: "bar")
|
6
|
+
|
7
|
+
expect(context).to be_a(Context)
|
8
|
+
expect(context.foo).to eq("bar")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "builds an empty context if no hash is given" do
|
12
|
+
context = Context.build
|
13
|
+
|
14
|
+
expect(context).to be_a(Context)
|
15
|
+
expect(context.send(:table)).to eq({})
|
16
|
+
end
|
17
|
+
|
18
|
+
it "doesn't affect the original hash" do
|
19
|
+
hash = {foo: "bar"}
|
20
|
+
context = Context.build(hash)
|
21
|
+
|
22
|
+
expect(context).to be_a(Context)
|
23
|
+
expect {
|
24
|
+
context.foo = "baz"
|
25
|
+
}.not_to change {
|
26
|
+
hash[:foo]
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
it "preserves an already built context" do
|
31
|
+
context1 = Context.build(foo: "bar")
|
32
|
+
context2 = Context.build(context1)
|
33
|
+
|
34
|
+
expect(context2).to be_a(Context)
|
35
|
+
expect {
|
36
|
+
context2.foo = "baz"
|
37
|
+
}.to change {
|
38
|
+
context1.foo
|
39
|
+
}.from("bar").to("baz")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#success?" do
|
44
|
+
let(:context) { Context.build }
|
45
|
+
|
46
|
+
it "is true by default" do
|
47
|
+
expect(context.success?).to eq(true)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#failure?" do
|
52
|
+
let(:context) { Context.build }
|
53
|
+
|
54
|
+
it "is false by default" do
|
55
|
+
expect(context.failure?).to eq(false)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#fail!" do
|
60
|
+
let(:context) { Context.build(foo: "bar") }
|
61
|
+
|
62
|
+
it "sets success to false" do
|
63
|
+
expect {
|
64
|
+
begin
|
65
|
+
context.fail!
|
66
|
+
rescue
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
}.to change {
|
70
|
+
context.success?
|
71
|
+
}.from(true).to(false)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "sets failure to true" do
|
75
|
+
expect {
|
76
|
+
begin
|
77
|
+
context.fail!
|
78
|
+
rescue
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
}.to change {
|
82
|
+
context.failure?
|
83
|
+
}.from(false).to(true)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "preserves failure" do
|
87
|
+
begin
|
88
|
+
context.fail!
|
89
|
+
rescue
|
90
|
+
nil
|
91
|
+
end
|
92
|
+
|
93
|
+
expect {
|
94
|
+
begin
|
95
|
+
context.fail!
|
96
|
+
rescue
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
}.not_to change {
|
100
|
+
context.failure?
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
it "preserves the context" do
|
105
|
+
expect {
|
106
|
+
begin
|
107
|
+
context.fail!
|
108
|
+
rescue
|
109
|
+
nil
|
110
|
+
end
|
111
|
+
}.not_to change {
|
112
|
+
context.foo
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
it "updates the context" do
|
117
|
+
expect {
|
118
|
+
begin
|
119
|
+
context.fail!(foo: "baz")
|
120
|
+
rescue
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
}.to change {
|
124
|
+
context.foo
|
125
|
+
}.from("bar").to("baz")
|
126
|
+
end
|
127
|
+
|
128
|
+
it "updates the context with a string key" do
|
129
|
+
expect {
|
130
|
+
begin
|
131
|
+
context.fail!("foo" => "baz")
|
132
|
+
rescue
|
133
|
+
nil
|
134
|
+
end
|
135
|
+
}.to change {
|
136
|
+
context.foo
|
137
|
+
}.from("bar").to("baz")
|
138
|
+
end
|
139
|
+
|
140
|
+
it "raises failure" do
|
141
|
+
expect {
|
142
|
+
context.fail!
|
143
|
+
}.to raise_error(Failure)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "makes the context available from the failure" do
|
147
|
+
context.fail!
|
148
|
+
rescue Failure => error
|
149
|
+
expect(error.context).to eq(context)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "#called!" do
|
154
|
+
let(:context) { Context.build }
|
155
|
+
let(:instance1) { double(:instance1) }
|
156
|
+
let(:instance2) { double(:instance2) }
|
157
|
+
|
158
|
+
it "appends to the internal list of called instances" do
|
159
|
+
expect {
|
160
|
+
context.called!(instance1)
|
161
|
+
context.called!(instance2)
|
162
|
+
}.to change {
|
163
|
+
context._called
|
164
|
+
}.from([]).to([instance1, instance2])
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "#rollback!" do
|
169
|
+
let(:context) { Context.build }
|
170
|
+
let(:instance1) { double(:instance1) }
|
171
|
+
let(:instance2) { double(:instance2) }
|
172
|
+
|
173
|
+
before do
|
174
|
+
allow(context).to receive(:_called) { [instance1, instance2] }
|
175
|
+
end
|
176
|
+
|
177
|
+
it "rolls back each instance in reverse order" do
|
178
|
+
expect(instance2).to receive(:rollback).once.with(no_args).ordered
|
179
|
+
expect(instance1).to receive(:rollback).once.with(no_args).ordered
|
180
|
+
|
181
|
+
context.rollback!
|
182
|
+
end
|
183
|
+
|
184
|
+
it "ignores subsequent attempts" do
|
185
|
+
expect(instance2).to receive(:rollback).once
|
186
|
+
expect(instance1).to receive(:rollback).once
|
187
|
+
|
188
|
+
context.rollback!
|
189
|
+
context.rollback!
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "#_called" do
|
194
|
+
let(:context) { Context.build }
|
195
|
+
|
196
|
+
it "is empty by default" do
|
197
|
+
expect(context._called).to eq([])
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,358 @@
|
|
1
|
+
module Interactor
|
2
|
+
describe Hooks do
|
3
|
+
describe "#with_hooks" do
|
4
|
+
def build_hooked(&block)
|
5
|
+
hooked = Class.new.send(:include, Interactor::Hooks)
|
6
|
+
|
7
|
+
hooked.class_eval do
|
8
|
+
attr_reader :steps
|
9
|
+
|
10
|
+
def self.process
|
11
|
+
new.tap(&:process).steps
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@steps = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def process
|
19
|
+
with_hooks { steps << :process }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
hooked.class_eval(&block) if block
|
24
|
+
hooked
|
25
|
+
end
|
26
|
+
|
27
|
+
context "with an around hook method" do
|
28
|
+
let(:hooked) {
|
29
|
+
build_hooked do
|
30
|
+
around :add_around_before_and_around_after
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def add_around_before_and_around_after(hooked)
|
35
|
+
steps << :around_before
|
36
|
+
hooked.call
|
37
|
+
steps << :around_after
|
38
|
+
end
|
39
|
+
end
|
40
|
+
}
|
41
|
+
|
42
|
+
it "runs the around hook method" do
|
43
|
+
expect(hooked.process).to eq([
|
44
|
+
:around_before,
|
45
|
+
:process,
|
46
|
+
:around_after
|
47
|
+
])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "with an around hook block" do
|
52
|
+
let(:hooked) {
|
53
|
+
build_hooked do
|
54
|
+
around do |hooked|
|
55
|
+
steps << :around_before
|
56
|
+
hooked.call
|
57
|
+
steps << :around_after
|
58
|
+
end
|
59
|
+
end
|
60
|
+
}
|
61
|
+
|
62
|
+
it "runs the around hook block" do
|
63
|
+
expect(hooked.process).to eq([
|
64
|
+
:around_before,
|
65
|
+
:process,
|
66
|
+
:around_after
|
67
|
+
])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "with an around hook method and block in one call" do
|
72
|
+
let(:hooked) {
|
73
|
+
build_hooked do
|
74
|
+
around :add_around_before1_and_around_after1 do |hooked|
|
75
|
+
steps << :around_before2
|
76
|
+
hooked.call
|
77
|
+
steps << :around_after2
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def add_around_before1_and_around_after1(hooked)
|
83
|
+
steps << :around_before1
|
84
|
+
hooked.call
|
85
|
+
steps << :around_after1
|
86
|
+
end
|
87
|
+
end
|
88
|
+
}
|
89
|
+
|
90
|
+
it "runs the around hook method and block in order" do
|
91
|
+
expect(hooked.process).to eq([
|
92
|
+
:around_before1,
|
93
|
+
:around_before2,
|
94
|
+
:process,
|
95
|
+
:around_after2,
|
96
|
+
:around_after1
|
97
|
+
])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "with an around hook method and block in multiple calls" do
|
102
|
+
let(:hooked) {
|
103
|
+
build_hooked do
|
104
|
+
around do |hooked|
|
105
|
+
steps << :around_before1
|
106
|
+
hooked.call
|
107
|
+
steps << :around_after1
|
108
|
+
end
|
109
|
+
|
110
|
+
around :add_around_before2_and_around_after2
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def add_around_before2_and_around_after2(hooked)
|
115
|
+
steps << :around_before2
|
116
|
+
hooked.call
|
117
|
+
steps << :around_after2
|
118
|
+
end
|
119
|
+
end
|
120
|
+
}
|
121
|
+
|
122
|
+
it "runs the around hook block and method in order" do
|
123
|
+
expect(hooked.process).to eq([
|
124
|
+
:around_before1,
|
125
|
+
:around_before2,
|
126
|
+
:process,
|
127
|
+
:around_after2,
|
128
|
+
:around_after1
|
129
|
+
])
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "with a before hook method" do
|
134
|
+
let(:hooked) {
|
135
|
+
build_hooked do
|
136
|
+
before :add_before
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def add_before
|
141
|
+
steps << :before
|
142
|
+
end
|
143
|
+
end
|
144
|
+
}
|
145
|
+
|
146
|
+
it "runs the before hook method" do
|
147
|
+
expect(hooked.process).to eq([
|
148
|
+
:before,
|
149
|
+
:process
|
150
|
+
])
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "with a before hook block" do
|
155
|
+
let(:hooked) {
|
156
|
+
build_hooked do
|
157
|
+
before do
|
158
|
+
steps << :before
|
159
|
+
end
|
160
|
+
end
|
161
|
+
}
|
162
|
+
|
163
|
+
it "runs the before hook block" do
|
164
|
+
expect(hooked.process).to eq([
|
165
|
+
:before,
|
166
|
+
:process
|
167
|
+
])
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "with a before hook method and block in one call" do
|
172
|
+
let(:hooked) {
|
173
|
+
build_hooked do
|
174
|
+
before :add_before1 do
|
175
|
+
steps << :before2
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
|
180
|
+
def add_before1
|
181
|
+
steps << :before1
|
182
|
+
end
|
183
|
+
end
|
184
|
+
}
|
185
|
+
|
186
|
+
it "runs the before hook method and block in order" do
|
187
|
+
expect(hooked.process).to eq([
|
188
|
+
:before1,
|
189
|
+
:before2,
|
190
|
+
:process
|
191
|
+
])
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context "with a before hook method and block in multiple calls" do
|
196
|
+
let(:hooked) {
|
197
|
+
build_hooked do
|
198
|
+
before do
|
199
|
+
steps << :before1
|
200
|
+
end
|
201
|
+
|
202
|
+
before :add_before2
|
203
|
+
|
204
|
+
private
|
205
|
+
|
206
|
+
def add_before2
|
207
|
+
steps << :before2
|
208
|
+
end
|
209
|
+
end
|
210
|
+
}
|
211
|
+
|
212
|
+
it "runs the before hook block and method in order" do
|
213
|
+
expect(hooked.process).to eq([
|
214
|
+
:before1,
|
215
|
+
:before2,
|
216
|
+
:process
|
217
|
+
])
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context "with an after hook method" do
|
222
|
+
let(:hooked) {
|
223
|
+
build_hooked do
|
224
|
+
after :add_after
|
225
|
+
|
226
|
+
private
|
227
|
+
|
228
|
+
def add_after
|
229
|
+
steps << :after
|
230
|
+
end
|
231
|
+
end
|
232
|
+
}
|
233
|
+
|
234
|
+
it "runs the after hook method" do
|
235
|
+
expect(hooked.process).to eq([
|
236
|
+
:process,
|
237
|
+
:after
|
238
|
+
])
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
context "with an after hook block" do
|
243
|
+
let(:hooked) {
|
244
|
+
build_hooked do
|
245
|
+
after do
|
246
|
+
steps << :after
|
247
|
+
end
|
248
|
+
end
|
249
|
+
}
|
250
|
+
|
251
|
+
it "runs the after hook block" do
|
252
|
+
expect(hooked.process).to eq([
|
253
|
+
:process,
|
254
|
+
:after
|
255
|
+
])
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context "with an after hook method and block in one call" do
|
260
|
+
let(:hooked) {
|
261
|
+
build_hooked do
|
262
|
+
after :add_after1 do
|
263
|
+
steps << :after2
|
264
|
+
end
|
265
|
+
|
266
|
+
private
|
267
|
+
|
268
|
+
def add_after1
|
269
|
+
steps << :after1
|
270
|
+
end
|
271
|
+
end
|
272
|
+
}
|
273
|
+
|
274
|
+
it "runs the after hook method and block in order" do
|
275
|
+
expect(hooked.process).to eq([
|
276
|
+
:process,
|
277
|
+
:after2,
|
278
|
+
:after1
|
279
|
+
])
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context "with an after hook method and block in multiple calls" do
|
284
|
+
let(:hooked) {
|
285
|
+
build_hooked do
|
286
|
+
after do
|
287
|
+
steps << :after1
|
288
|
+
end
|
289
|
+
|
290
|
+
after :add_after2
|
291
|
+
|
292
|
+
private
|
293
|
+
|
294
|
+
def add_after2
|
295
|
+
steps << :after2
|
296
|
+
end
|
297
|
+
end
|
298
|
+
}
|
299
|
+
|
300
|
+
it "runs the after hook block and method in order" do
|
301
|
+
expect(hooked.process).to eq([
|
302
|
+
:process,
|
303
|
+
:after2,
|
304
|
+
:after1
|
305
|
+
])
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
context "with around, before and after hooks" do
|
310
|
+
let(:hooked) {
|
311
|
+
build_hooked do
|
312
|
+
around do |hooked|
|
313
|
+
steps << :around_before1
|
314
|
+
hooked.call
|
315
|
+
steps << :around_after1
|
316
|
+
end
|
317
|
+
|
318
|
+
around do |hooked|
|
319
|
+
steps << :around_before2
|
320
|
+
hooked.call
|
321
|
+
steps << :around_after2
|
322
|
+
end
|
323
|
+
|
324
|
+
before do
|
325
|
+
steps << :before1
|
326
|
+
end
|
327
|
+
|
328
|
+
before do
|
329
|
+
steps << :before2
|
330
|
+
end
|
331
|
+
|
332
|
+
after do
|
333
|
+
steps << :after1
|
334
|
+
end
|
335
|
+
|
336
|
+
after do
|
337
|
+
steps << :after2
|
338
|
+
end
|
339
|
+
end
|
340
|
+
}
|
341
|
+
|
342
|
+
it "runs hooks in the proper order" do
|
343
|
+
expect(hooked.process).to eq([
|
344
|
+
:around_before1,
|
345
|
+
:around_before2,
|
346
|
+
:before1,
|
347
|
+
:before2,
|
348
|
+
:process,
|
349
|
+
:after2,
|
350
|
+
:after1,
|
351
|
+
:around_after2,
|
352
|
+
:around_after1
|
353
|
+
])
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Interactor
|
2
|
+
describe Organizer do
|
3
|
+
include_examples :lint
|
4
|
+
|
5
|
+
let(:organizer) { Class.new.send(:include, Organizer) }
|
6
|
+
|
7
|
+
describe ".organize" do
|
8
|
+
let(:interactor2) { double(:interactor2) }
|
9
|
+
let(:interactor3) { double(:interactor3) }
|
10
|
+
|
11
|
+
it "sets interactors given class arguments" do
|
12
|
+
expect {
|
13
|
+
organizer.organize(interactor2, interactor3)
|
14
|
+
}.to change {
|
15
|
+
organizer.organized
|
16
|
+
}.from([]).to([interactor2, interactor3])
|
17
|
+
end
|
18
|
+
|
19
|
+
it "sets interactors given an array of classes" do
|
20
|
+
expect {
|
21
|
+
organizer.organize([interactor2, interactor3])
|
22
|
+
}.to change {
|
23
|
+
organizer.organized
|
24
|
+
}.from([]).to([interactor2, interactor3])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ".organized" do
|
29
|
+
it "is empty by default" do
|
30
|
+
expect(organizer.organized).to eq([])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#call" do
|
35
|
+
let(:instance) { organizer.new }
|
36
|
+
let(:context) { double(:context) }
|
37
|
+
let(:interactor2) { double(:interactor2) }
|
38
|
+
let(:interactor3) { double(:interactor3) }
|
39
|
+
let(:interactor4) { double(:interactor4) }
|
40
|
+
|
41
|
+
before do
|
42
|
+
allow(instance).to receive(:context) { context }
|
43
|
+
allow(organizer).to receive(:organized) {
|
44
|
+
[interactor2, interactor3, interactor4]
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
it "calls each interactor in order with the context" do
|
49
|
+
expect(interactor2).to receive(:call!).once.with(context).ordered
|
50
|
+
expect(interactor3).to receive(:call!).once.with(context).ordered
|
51
|
+
expect(interactor4).to receive(:call!).once.with(context).ordered
|
52
|
+
|
53
|
+
instance.call
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "interactor/strict"
|
4
|
+
|
5
|
+
RSpec.describe Interactor::Strict do
|
6
|
+
let(:service_class) do
|
7
|
+
Class.new do
|
8
|
+
include Interactor
|
9
|
+
include Interactor::Strict
|
10
|
+
|
11
|
+
before :before_one
|
12
|
+
before :before_two
|
13
|
+
after :after_one
|
14
|
+
after :after_two
|
15
|
+
|
16
|
+
def call(foo:, bar:, with_default: 'default')
|
17
|
+
context.args = [foo, bar, with_default]
|
18
|
+
end
|
19
|
+
|
20
|
+
def before_one
|
21
|
+
context.hooks = ["before_one"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def before_two
|
25
|
+
context.hooks << "before_two"
|
26
|
+
end
|
27
|
+
|
28
|
+
def after_one
|
29
|
+
context.hooks << "after_one"
|
30
|
+
end
|
31
|
+
|
32
|
+
def after_two
|
33
|
+
context.hooks << "after_two"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
let(:loose_params_service) do
|
40
|
+
Class.new do
|
41
|
+
include Interactor
|
42
|
+
include Interactor::Strict
|
43
|
+
|
44
|
+
def call(foo:, bar:, **others)
|
45
|
+
context.args = [foo, bar, others]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe ".call" do
|
51
|
+
context "when they are defined" do
|
52
|
+
it "works when all keyword arguments are passed" do
|
53
|
+
context = service_class.call(foo: "the-foo", bar: "the-bar")
|
54
|
+
|
55
|
+
expect(context.args).to eq(%w[the-foo the-bar default])
|
56
|
+
end
|
57
|
+
|
58
|
+
it "works with regular hooks" do
|
59
|
+
context = service_class.call(foo: "the-foo", bar: "the-bar")
|
60
|
+
|
61
|
+
expect(context.hooks).to eq(%w[before_one before_two after_two after_one])
|
62
|
+
end
|
63
|
+
|
64
|
+
it "can take looser params" do
|
65
|
+
context = loose_params_service.call(foo: "foo", bar: "bar", other: "other")
|
66
|
+
|
67
|
+
expect(context.args).to eq(["foo", "bar", { other: "other"}])
|
68
|
+
end
|
69
|
+
|
70
|
+
it "raises when keyword arguments are not properly passed" do
|
71
|
+
expect { service_class.call(foo: "the-foo") }.to raise_error(ArgumentError)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe ".call!" do
|
77
|
+
context "when they are defined" do
|
78
|
+
it "works when all keyword arguments are passed" do
|
79
|
+
context = service_class.call!(foo: "the-foo", bar: "the-bar")
|
80
|
+
|
81
|
+
expect(context.args).to eq(%w[the-foo the-bar default])
|
82
|
+
end
|
83
|
+
|
84
|
+
it "works with regular hooks" do
|
85
|
+
context = service_class.call!(foo: "the-foo", bar: "the-bar")
|
86
|
+
|
87
|
+
expect(context.hooks).to eq(%w[before_one before_two after_two after_one])
|
88
|
+
end
|
89
|
+
|
90
|
+
it "raises when keyword arguments are not properly passed" do
|
91
|
+
expect { service_class.call!(foo: "the-foo") }.to raise_error(ArgumentError)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|