interaktor 0.5.1 → 0.6.0.pre
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 +4 -4
- data/README.md +79 -69
- data/interaktor.gemspec +2 -2
- data/lib/interaktor/attributes.rb +24 -0
- data/lib/interaktor/callable.rb +42 -262
- data/lib/interaktor/error/attribute_error.rb +2 -2
- data/lib/interaktor/error/attribute_validation_error.rb +20 -0
- data/lib/interaktor/error/missing_explicit_success_error.rb +7 -2
- data/lib/interaktor/error/organizer_missing_passed_attribute_error.rb +7 -7
- data/lib/interaktor/error/organizer_success_attribute_missing_error.rb +4 -4
- data/lib/interaktor/error/unknown_attribute_error.rb +4 -4
- data/lib/interaktor/interaction.rb +83 -29
- data/lib/interaktor/organizer.rb +7 -35
- data/lib/interaktor.rb +2 -18
- data/spec/interaktor/hooks_spec.rb +357 -363
- data/spec/interaktor/organizer_spec.rb +57 -48
- data/spec/support/helpers.rb +13 -2
- data/spec/support/lint.rb +219 -271
- metadata +11 -11
- data/lib/interaktor/error/attribute_schema_validation_error.rb +0 -54
- data/spec/interaktor/context_spec.rb +0 -187
data/spec/support/lint.rb
CHANGED
|
@@ -13,7 +13,7 @@ RSpec.shared_examples "lint" do |interaktor_class|
|
|
|
13
13
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class)
|
|
14
14
|
|
|
15
15
|
expect {
|
|
16
|
-
interaktor.call(
|
|
16
|
+
interaktor.call(foo: "bar")
|
|
17
17
|
}.to raise_error(Interaktor::Error::UnknownAttributeError)
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -133,464 +133,412 @@ RSpec.shared_examples "lint" do |interaktor_class|
|
|
|
133
133
|
end
|
|
134
134
|
end
|
|
135
135
|
|
|
136
|
-
describe "
|
|
137
|
-
it "
|
|
138
|
-
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
139
|
-
input
|
|
140
|
-
required(:foo)
|
|
141
|
-
required(:bar)
|
|
142
|
-
optional(:baz)
|
|
143
|
-
end
|
|
136
|
+
describe "input attributes" do
|
|
137
|
+
it "accepts an attribute definition block" do
|
|
138
|
+
interaktor = FakeInteraktor.build_interaktor("MyCoolFoo", type: interaktor_class) do
|
|
139
|
+
input { attribute :foo }
|
|
144
140
|
end
|
|
145
141
|
|
|
146
|
-
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
it "returns empty array when not defined" do
|
|
150
|
-
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class)
|
|
142
|
+
result = interaktor.call(foo: "bar")
|
|
151
143
|
|
|
152
|
-
expect(
|
|
144
|
+
expect(result.success?).to be true
|
|
145
|
+
expect { result.foo }.to raise_error(NoMethodError)
|
|
153
146
|
end
|
|
154
|
-
end
|
|
155
147
|
|
|
156
|
-
|
|
157
|
-
it "returns the attributes" do
|
|
148
|
+
it "raises an exception when the attribute is required and not provided" do
|
|
158
149
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
159
150
|
input do
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
optional(:baz)
|
|
151
|
+
attribute :foo
|
|
152
|
+
validates :foo, presence: true
|
|
163
153
|
end
|
|
164
154
|
end
|
|
165
155
|
|
|
166
|
-
expect
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
156
|
+
expect {
|
|
157
|
+
interaktor.call!
|
|
158
|
+
}.to raise_error do |error|
|
|
159
|
+
expect(error).to be_an Interaktor::Error::AttributeValidationError
|
|
160
|
+
expect(error.validation_errors).to eq(
|
|
161
|
+
foo: ["can't be blank"]
|
|
162
|
+
)
|
|
163
|
+
end
|
|
173
164
|
end
|
|
174
|
-
end
|
|
175
165
|
|
|
176
|
-
|
|
177
|
-
it "returns both required and optional attributes" do
|
|
166
|
+
it "raises an exception for unknown provided attributes" do
|
|
178
167
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
179
|
-
input
|
|
180
|
-
required(:foo)
|
|
181
|
-
required(:bar)
|
|
182
|
-
optional(:baz)
|
|
183
|
-
end
|
|
168
|
+
input { attribute :foo }
|
|
184
169
|
end
|
|
185
170
|
|
|
186
|
-
expect
|
|
171
|
+
expect {
|
|
172
|
+
interaktor.call!(foo: "baz", bar: "unexpected")
|
|
173
|
+
}.to raise_error do |error|
|
|
174
|
+
expect(error).to be_an Interaktor::Error::UnknownAttributeError
|
|
175
|
+
expect(error.attribute).to eq "bar"
|
|
176
|
+
end
|
|
187
177
|
end
|
|
188
|
-
end
|
|
189
178
|
|
|
190
|
-
|
|
191
|
-
it "returns the attributes" do
|
|
179
|
+
it "allows provided optional attributes" do
|
|
192
180
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
193
|
-
|
|
194
|
-
required(:foo)
|
|
195
|
-
required(:bar)
|
|
196
|
-
optional(:baz)
|
|
197
|
-
end
|
|
181
|
+
input { attribute :foo }
|
|
198
182
|
end
|
|
199
183
|
|
|
200
|
-
|
|
201
|
-
end
|
|
184
|
+
result = interaktor.call(foo: "bar")
|
|
202
185
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
expect(interaktor.required_success_attributes).to be_empty
|
|
186
|
+
expect(result.success?).to be true
|
|
187
|
+
expect { result.foo }.to raise_error(NoMethodError)
|
|
207
188
|
end
|
|
208
|
-
end
|
|
209
189
|
|
|
210
|
-
|
|
211
|
-
it "returns the attributes" do
|
|
190
|
+
it "allows missing optional attributes" do
|
|
212
191
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
213
|
-
|
|
214
|
-
required(:foo)
|
|
215
|
-
required(:bar)
|
|
216
|
-
optional(:baz)
|
|
217
|
-
end
|
|
192
|
+
input { attribute :foo }
|
|
218
193
|
end
|
|
219
194
|
|
|
220
|
-
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
it "returns empty array when not defined" do
|
|
224
|
-
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class)
|
|
195
|
+
result = interaktor.call
|
|
225
196
|
|
|
226
|
-
expect(
|
|
197
|
+
expect(result.success?).to be true
|
|
198
|
+
expect { result.foo }.to raise_error(NoMethodError)
|
|
227
199
|
end
|
|
228
|
-
end
|
|
229
200
|
|
|
230
|
-
|
|
231
|
-
it "returns both required and optional attributes" do
|
|
201
|
+
it "creates attribute getters" do
|
|
232
202
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
233
|
-
|
|
234
|
-
required(:foo)
|
|
235
|
-
required(:bar)
|
|
236
|
-
optional(:baz)
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
expect(interaktor.success_attributes).to contain_exactly(:foo, :bar, :baz)
|
|
241
|
-
end
|
|
242
|
-
end
|
|
203
|
+
input { attribute :foo }
|
|
243
204
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
247
|
-
failure do
|
|
248
|
-
required(:foo)
|
|
249
|
-
required(:bar)
|
|
250
|
-
optional(:baz)
|
|
205
|
+
def call
|
|
206
|
+
foo
|
|
251
207
|
end
|
|
252
208
|
end
|
|
253
209
|
|
|
254
|
-
|
|
255
|
-
end
|
|
210
|
+
result = interaktor.call(foo: "bar")
|
|
256
211
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
expect(interaktor.required_failure_attributes).to be_empty
|
|
212
|
+
expect(result.success?).to be true
|
|
213
|
+
expect { result.foo }.to raise_error(NoMethodError)
|
|
214
|
+
expect { result.bar }.to raise_error(NoMethodError)
|
|
261
215
|
end
|
|
262
|
-
end
|
|
263
216
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
required(:bar)
|
|
270
|
-
optional(:baz)
|
|
217
|
+
it "disallows specifically disallowed attribute names" do
|
|
218
|
+
expect {
|
|
219
|
+
FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
220
|
+
# 'errors' is one because it's the accessor for the ActiveModel::Errors
|
|
221
|
+
input { attribute :errors }
|
|
271
222
|
end
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
expect(interaktor.optional_failure_attributes).to contain_exactly(:baz)
|
|
223
|
+
}.to raise_error(ArgumentError, /disallowed attribute name/i)
|
|
275
224
|
end
|
|
276
225
|
|
|
277
|
-
it "
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
describe "#failure_attributes" do
|
|
285
|
-
it "returns both required and optional attributes" do
|
|
286
|
-
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
287
|
-
failure do
|
|
288
|
-
required(:foo)
|
|
289
|
-
required(:bar)
|
|
290
|
-
optional(:baz)
|
|
226
|
+
it "raises an exception when input block is provided more than once" do
|
|
227
|
+
expect {
|
|
228
|
+
FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
229
|
+
input { attribute :foo }
|
|
230
|
+
input { attribute :bar }
|
|
291
231
|
end
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
expect(interaktor.failure_attributes).to contain_exactly(:foo, :bar, :baz)
|
|
232
|
+
}.to raise_error "Input block already defined"
|
|
295
233
|
end
|
|
296
234
|
end
|
|
297
235
|
|
|
298
|
-
describe "
|
|
299
|
-
it "accepts
|
|
236
|
+
describe "success attributes" do
|
|
237
|
+
it "accepts an attribute definition block" do
|
|
300
238
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
301
|
-
|
|
302
|
-
end
|
|
239
|
+
success { attribute :foo }
|
|
303
240
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
result = interaktor.call(bar: "baz")
|
|
308
|
-
|
|
309
|
-
expect(result.success?).to be true
|
|
310
|
-
expect { result.bar }.to raise_error(NoMethodError)
|
|
311
|
-
end
|
|
312
|
-
|
|
313
|
-
it "accepts a schema definition block" do
|
|
314
|
-
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
315
|
-
input { required(:bar).filled(:string) }
|
|
241
|
+
def call
|
|
242
|
+
success!(foo: "bar")
|
|
243
|
+
end
|
|
316
244
|
end
|
|
317
245
|
|
|
318
|
-
|
|
319
|
-
expect(interaktor.required_input_attributes).to contain_exactly(:bar)
|
|
320
|
-
|
|
321
|
-
result = interaktor.call(bar: "baz")
|
|
246
|
+
result = interaktor.call
|
|
322
247
|
|
|
323
248
|
expect(result.success?).to be true
|
|
324
|
-
expect
|
|
249
|
+
expect(result.foo).to eq "bar"
|
|
325
250
|
end
|
|
326
251
|
|
|
327
252
|
it "raises an exception when the attribute is required and not provided" do
|
|
328
253
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
329
|
-
|
|
254
|
+
success do
|
|
255
|
+
attribute :foo
|
|
256
|
+
validates :foo, presence: true
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def call
|
|
260
|
+
success!
|
|
261
|
+
end
|
|
330
262
|
end
|
|
331
263
|
|
|
332
264
|
expect {
|
|
333
265
|
interaktor.call!
|
|
334
|
-
}.to raise_error
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
validation_errors: {bar: ["is missing"]}
|
|
339
|
-
)
|
|
266
|
+
}.to raise_error do |error|
|
|
267
|
+
expect(error).to be_an Interaktor::Error::AttributeValidationError
|
|
268
|
+
expect(error.validation_errors).to eq(
|
|
269
|
+
foo: ["can't be blank"]
|
|
340
270
|
)
|
|
341
|
-
|
|
271
|
+
end
|
|
342
272
|
end
|
|
343
273
|
|
|
344
274
|
it "raises an exception for unknown provided attributes" do
|
|
345
275
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
346
|
-
|
|
276
|
+
success { attribute :foo }
|
|
277
|
+
|
|
278
|
+
def call
|
|
279
|
+
success!(baz: "wadus")
|
|
280
|
+
end
|
|
347
281
|
end
|
|
348
282
|
|
|
349
283
|
expect {
|
|
350
|
-
interaktor.call
|
|
351
|
-
}.to raise_error
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
it "allows provided optional attributes" do
|
|
355
|
-
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
356
|
-
input { optional(:bar).filled(:string) }
|
|
284
|
+
interaktor.call
|
|
285
|
+
}.to raise_error do |error|
|
|
286
|
+
expect(error).to be_an Interaktor::Error::UnknownAttributeError
|
|
287
|
+
expect(error.attribute).to eq "baz"
|
|
357
288
|
end
|
|
358
|
-
|
|
359
|
-
expect(interaktor.optional_input_attributes).to contain_exactly(:bar)
|
|
360
|
-
|
|
361
|
-
result = interaktor.call(bar: "baz")
|
|
362
|
-
|
|
363
|
-
expect(result.success?).to be true
|
|
364
|
-
expect { result.bar }.to raise_error(NoMethodError)
|
|
365
289
|
end
|
|
366
290
|
|
|
367
|
-
it "allows
|
|
291
|
+
it "allows success with no attributes" do
|
|
368
292
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
369
|
-
|
|
293
|
+
def call
|
|
294
|
+
success!
|
|
295
|
+
end
|
|
370
296
|
end
|
|
371
297
|
|
|
372
|
-
expect(interaktor.optional_input_attributes).to contain_exactly(:bar)
|
|
373
|
-
|
|
374
298
|
result = interaktor.call
|
|
375
299
|
|
|
376
300
|
expect(result.success?).to be true
|
|
377
|
-
expect
|
|
301
|
+
expect(result.early_return?).to be true
|
|
378
302
|
end
|
|
379
303
|
|
|
380
|
-
it "
|
|
304
|
+
it "allows provided optional attributes" do
|
|
381
305
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
382
|
-
|
|
383
|
-
required(:foo).filled(:string)
|
|
384
|
-
optional(:bar).filled(:string)
|
|
385
|
-
end
|
|
306
|
+
success { attribute :foo }
|
|
386
307
|
|
|
387
308
|
def call
|
|
388
|
-
foo
|
|
389
|
-
bar
|
|
309
|
+
success!(foo: "bar")
|
|
390
310
|
end
|
|
391
311
|
end
|
|
392
312
|
|
|
393
|
-
result = interaktor.call
|
|
313
|
+
result = interaktor.call
|
|
394
314
|
|
|
395
315
|
expect(result.success?).to be true
|
|
396
|
-
expect
|
|
397
|
-
expect { result.bar }.to raise_error(NoMethodError)
|
|
316
|
+
expect(result.foo).to eq "bar"
|
|
398
317
|
end
|
|
399
|
-
end
|
|
400
318
|
|
|
401
|
-
|
|
402
|
-
it "accepts a schema object" do
|
|
319
|
+
it "allows missing optional attributes" do
|
|
403
320
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
404
|
-
success
|
|
321
|
+
success { attribute :foo }
|
|
405
322
|
|
|
406
323
|
def call
|
|
407
|
-
success!
|
|
324
|
+
success!
|
|
408
325
|
end
|
|
409
326
|
end
|
|
410
327
|
|
|
411
|
-
expect(interaktor.success_schema).to be_a Dry::Schema::Params
|
|
412
|
-
expect(interaktor.required_success_attributes).to contain_exactly(:bar)
|
|
413
|
-
|
|
414
328
|
result = interaktor.call
|
|
415
329
|
|
|
416
330
|
expect(result.success?).to be true
|
|
417
|
-
expect(result.
|
|
331
|
+
expect(result.foo).to be nil
|
|
418
332
|
end
|
|
419
333
|
|
|
420
|
-
it "
|
|
334
|
+
it "raises an exception when attributes are provided but none are defined" do
|
|
421
335
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
422
|
-
success { required(:bar).filled(:string) }
|
|
423
|
-
|
|
424
336
|
def call
|
|
425
|
-
success!(
|
|
337
|
+
success!(foo: "bar")
|
|
426
338
|
end
|
|
427
339
|
end
|
|
428
340
|
|
|
429
|
-
expect
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
expect(result.bar).to eq "baz"
|
|
341
|
+
expect {
|
|
342
|
+
interaktor.call
|
|
343
|
+
}.to raise_error do |error|
|
|
344
|
+
expect(error).to be_a Interaktor::Error::UnknownAttributeError
|
|
345
|
+
expect(error.attribute).to eq "foo"
|
|
346
|
+
end
|
|
436
347
|
end
|
|
437
348
|
|
|
438
|
-
it "raises an exception when the
|
|
349
|
+
it "raises an exception when the correct attributes are not provided because #success! is not called" do
|
|
439
350
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
440
|
-
success {
|
|
351
|
+
success { attribute :foo }
|
|
441
352
|
|
|
442
353
|
def call
|
|
443
|
-
|
|
354
|
+
# do nothing and 'succeed' implicitly
|
|
444
355
|
end
|
|
445
356
|
end
|
|
446
357
|
|
|
447
|
-
expect {
|
|
448
|
-
interaktor.call
|
|
449
|
-
}.to raise_error(
|
|
450
|
-
an_instance_of(Interaktor::Error::AttributeSchemaValidationError).and(
|
|
451
|
-
having_attributes(
|
|
452
|
-
interaktor: interaktor,
|
|
453
|
-
validation_errors: {bar: ["is missing"]}
|
|
454
|
-
)
|
|
455
|
-
)
|
|
456
|
-
)
|
|
358
|
+
expect { interaktor.call }.to raise_error Interaktor::Error::MissingExplicitSuccessError
|
|
457
359
|
end
|
|
458
360
|
|
|
459
|
-
it "
|
|
361
|
+
it "does not create getters for failure attributes" do
|
|
460
362
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
461
|
-
success {
|
|
363
|
+
success { attribute :foo }
|
|
364
|
+
failure { attribute :baz }
|
|
462
365
|
|
|
463
366
|
def call
|
|
464
|
-
success!(
|
|
367
|
+
success!(foo: "bar")
|
|
465
368
|
end
|
|
466
369
|
end
|
|
467
370
|
|
|
371
|
+
result = interaktor.call
|
|
372
|
+
|
|
373
|
+
expect(result.success?).to be true
|
|
374
|
+
expect(result.foo).to eq "bar"
|
|
375
|
+
expect { result.baz }.to raise_error NoMethodError
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
it "disallows specifically disallowed attribute names" do
|
|
468
379
|
expect {
|
|
469
|
-
|
|
470
|
-
|
|
380
|
+
FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
381
|
+
# 'errors' is one because it's the accessor for the ActiveModel::Errors
|
|
382
|
+
success { attribute :errors }
|
|
383
|
+
end
|
|
384
|
+
}.to raise_error(ArgumentError, /disallowed attribute name/i)
|
|
471
385
|
end
|
|
472
386
|
|
|
473
|
-
it "
|
|
387
|
+
it "raises an exception when success block is provided more than once" do
|
|
388
|
+
expect {
|
|
389
|
+
FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
390
|
+
success { attribute :foo }
|
|
391
|
+
success { attribute :bar }
|
|
392
|
+
end
|
|
393
|
+
}.to raise_error "Success block already defined"
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
describe "failure attributes" do
|
|
398
|
+
it "accepts an attribute definition block" do
|
|
474
399
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
475
|
-
|
|
400
|
+
failure { attribute :foo }
|
|
476
401
|
|
|
477
402
|
def call
|
|
478
|
-
|
|
403
|
+
fail!(foo: "bar")
|
|
479
404
|
end
|
|
480
405
|
end
|
|
481
406
|
|
|
482
|
-
expect(interaktor.optional_success_attributes).to contain_exactly(:bar)
|
|
483
|
-
|
|
484
407
|
result = interaktor.call
|
|
485
408
|
|
|
486
|
-
expect(result.
|
|
487
|
-
expect(result.
|
|
409
|
+
expect(result.failure?).to be true
|
|
410
|
+
expect(result.foo).to eq "bar"
|
|
488
411
|
end
|
|
489
412
|
|
|
490
|
-
it "raises an exception when the
|
|
413
|
+
it "raises an exception when the attribute is required and not provided" do
|
|
491
414
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
492
|
-
|
|
415
|
+
failure do
|
|
416
|
+
attribute :foo
|
|
417
|
+
validates :foo, presence: true
|
|
418
|
+
end
|
|
493
419
|
|
|
494
420
|
def call
|
|
495
|
-
|
|
421
|
+
fail!
|
|
496
422
|
end
|
|
497
423
|
end
|
|
498
424
|
|
|
499
|
-
expect {
|
|
500
|
-
|
|
501
|
-
|
|
425
|
+
expect {
|
|
426
|
+
interaktor.call!
|
|
427
|
+
}.to raise_error do |error|
|
|
428
|
+
expect(error).to be_an Interaktor::Error::AttributeValidationError
|
|
429
|
+
expect(error.validation_errors).to eq(
|
|
430
|
+
foo: ["can't be blank"]
|
|
502
431
|
)
|
|
503
|
-
|
|
432
|
+
end
|
|
504
433
|
end
|
|
505
|
-
end
|
|
506
434
|
|
|
507
|
-
|
|
508
|
-
it "accepts a schema object" do
|
|
435
|
+
it "raises an exception for unknown provided attributes" do
|
|
509
436
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
510
|
-
failure
|
|
437
|
+
failure { attribute :foo }
|
|
511
438
|
|
|
512
439
|
def call
|
|
513
|
-
fail!(
|
|
440
|
+
fail!(baz: "wadus")
|
|
514
441
|
end
|
|
515
442
|
end
|
|
516
443
|
|
|
517
|
-
expect
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
expect(result.bar).to eq "baz"
|
|
444
|
+
expect {
|
|
445
|
+
interaktor.call
|
|
446
|
+
}.to raise_error do |error|
|
|
447
|
+
expect(error).to be_an Interaktor::Error::UnknownAttributeError
|
|
448
|
+
expect(error.attribute).to eq "baz"
|
|
449
|
+
end
|
|
524
450
|
end
|
|
525
451
|
|
|
526
|
-
it "
|
|
452
|
+
it "allows failure with no attributes" do
|
|
527
453
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
528
|
-
failure { required(:bar).filled(:string) }
|
|
529
|
-
|
|
530
454
|
def call
|
|
531
|
-
fail!
|
|
455
|
+
fail!
|
|
532
456
|
end
|
|
533
457
|
end
|
|
534
458
|
|
|
535
|
-
expect(interaktor.failure_schema).to be_a Dry::Schema::Params
|
|
536
|
-
expect(interaktor.required_failure_attributes).to contain_exactly(:bar)
|
|
537
|
-
|
|
538
459
|
result = interaktor.call
|
|
539
460
|
|
|
540
461
|
expect(result.failure?).to be true
|
|
541
|
-
expect(result.bar).to eq "baz"
|
|
542
462
|
end
|
|
543
463
|
|
|
544
|
-
it "raises an exception when
|
|
464
|
+
it "raises an exception when attributes are provided but none are defined" do
|
|
545
465
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
546
|
-
failure { required(:bar).filled(:string) }
|
|
547
|
-
|
|
548
466
|
def call
|
|
549
|
-
fail!
|
|
467
|
+
fail!(foo: "bar")
|
|
550
468
|
end
|
|
551
469
|
end
|
|
552
470
|
|
|
553
471
|
expect {
|
|
554
472
|
interaktor.call
|
|
555
|
-
}.to raise_error
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
validation_errors: {bar: ["is missing"]}
|
|
560
|
-
)
|
|
561
|
-
)
|
|
562
|
-
)
|
|
473
|
+
}.to raise_error do |error|
|
|
474
|
+
expect(error).to be_a Interaktor::Error::UnknownAttributeError
|
|
475
|
+
expect(error.attribute).to eq "foo"
|
|
476
|
+
end
|
|
563
477
|
end
|
|
564
478
|
|
|
565
|
-
it "
|
|
479
|
+
it "allows provided optional attributes" do
|
|
566
480
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
567
|
-
failure {
|
|
481
|
+
failure { attribute :foo }
|
|
568
482
|
|
|
569
483
|
def call
|
|
570
|
-
fail!(
|
|
484
|
+
fail!(foo: "bar")
|
|
571
485
|
end
|
|
572
486
|
end
|
|
573
487
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
488
|
+
result = interaktor.call
|
|
489
|
+
|
|
490
|
+
expect(result.failure?).to be true
|
|
491
|
+
expect(result.foo).to eq "bar"
|
|
577
492
|
end
|
|
578
493
|
|
|
579
494
|
it "allows missing optional attributes" do
|
|
580
495
|
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
581
|
-
failure {
|
|
496
|
+
failure { attribute :foo }
|
|
582
497
|
|
|
583
498
|
def call
|
|
584
499
|
fail!
|
|
585
500
|
end
|
|
586
501
|
end
|
|
587
502
|
|
|
588
|
-
|
|
503
|
+
result = interaktor.call
|
|
504
|
+
|
|
505
|
+
expect(result.failure?).to be true
|
|
506
|
+
expect(result.foo).to be nil
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
it "does not create getters for success attributes" do
|
|
510
|
+
interaktor = FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
511
|
+
success { attribute :foo }
|
|
512
|
+
failure { attribute :baz }
|
|
513
|
+
|
|
514
|
+
def call
|
|
515
|
+
fail!(baz: "wadus")
|
|
516
|
+
end
|
|
517
|
+
end
|
|
589
518
|
|
|
590
519
|
result = interaktor.call
|
|
591
520
|
|
|
592
521
|
expect(result.failure?).to be true
|
|
593
|
-
expect(result.
|
|
522
|
+
expect(result.baz).to eq "wadus"
|
|
523
|
+
expect { result.foo }.to raise_error NoMethodError
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
it "disallows specifically disallowed attribute names" do
|
|
527
|
+
expect {
|
|
528
|
+
FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
529
|
+
# 'errors' is one because it's the accessor for the ActiveModel::Errors
|
|
530
|
+
failure { attribute :errors }
|
|
531
|
+
end
|
|
532
|
+
}.to raise_error(ArgumentError, /disallowed attribute name/i)
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
it "raises an exception when failure block is provided more than once" do
|
|
536
|
+
expect {
|
|
537
|
+
FakeInteraktor.build_interaktor(type: interaktor_class) do
|
|
538
|
+
failure { attribute :foo }
|
|
539
|
+
failure { attribute :bar }
|
|
540
|
+
end
|
|
541
|
+
}.to raise_error "Failure block already defined"
|
|
594
542
|
end
|
|
595
543
|
end
|
|
596
544
|
end
|