functional-light-service 6.0.0 → 6.2.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 +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG.md +26 -0
- data/README.md +130 -11
- data/functional-light-service.gemspec +3 -1
- data/lib/functional-light-service/action.rb +48 -0
- data/lib/functional-light-service/configuration.rb +12 -2
- data/lib/functional-light-service/context/key_verifier.rb +1 -1
- data/lib/functional-light-service/context.rb +15 -2
- data/lib/functional-light-service/errors.rb +1 -0
- data/lib/functional-light-service/functional/sequencer.rb +144 -0
- data/lib/functional-light-service/i18n/localization_adapter.rb +50 -0
- data/lib/functional-light-service/localization_adapter.rb +19 -28
- data/lib/functional-light-service/localization_map.rb +9 -0
- data/lib/functional-light-service/organizer/reduce_case.rb +50 -0
- data/lib/functional-light-service/organizer/reduce_if_else.rb +23 -0
- data/lib/functional-light-service/organizer/reduce_until.rb +1 -1
- data/lib/functional-light-service/organizer/reduce_while.rb +31 -0
- data/lib/functional-light-service/organizer/scoped_reducable.rb +2 -2
- data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +2 -1
- data/lib/functional-light-service/organizer.rb +18 -3
- data/lib/functional-light-service/version.rb +1 -1
- data/lib/functional-light-service.rb +6 -0
- data/spec/acceptance/organizer/add_to_context_spec.rb +24 -0
- data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +22 -0
- data/spec/acceptance/organizer/execute_spec.rb +21 -0
- data/spec/acceptance/organizer/reduce_case_spec.rb +65 -0
- data/spec/acceptance/organizer/reduce_if_else_spec.rb +60 -0
- data/spec/acceptance/organizer/reduce_while_spec.rb +96 -0
- data/spec/acceptance/skip_all_remaining_spec.rb +139 -0
- data/spec/action_optional_expected_keys_spec.rb +107 -0
- data/spec/context/inspect_spec.rb +13 -3
- data/spec/context_spec.rb +12 -0
- data/spec/i18n_localization_adapter_spec.rb +83 -0
- data/spec/lib/deterministic/sequencer_spec.rb +506 -0
- data/spec/localization_adapter_spec.rb +66 -83
- data/spec/spec_helper.rb +3 -0
- data/spec/test_doubles.rb +28 -0
- metadata +27 -14
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe FunctionalLightService::Sequencer do
|
|
4
|
+
include FunctionalLightService::Prelude::Result
|
|
5
|
+
|
|
6
|
+
let(:test_class) { Class.new { include FunctionalLightService::Sequencer } }
|
|
7
|
+
let(:test_instance) { test_class.new }
|
|
8
|
+
let(:arbitrary_success) { Success(double) }
|
|
9
|
+
|
|
10
|
+
# This mock method makes #arbitrary_success available within the operations
|
|
11
|
+
# in the test sequences
|
|
12
|
+
before { allow(test_instance).to receive(:arbitrary_success).and_return(arbitrary_success) }
|
|
13
|
+
|
|
14
|
+
it 'requires #and_yield to be specified' do
|
|
15
|
+
expect do
|
|
16
|
+
in_sequence do
|
|
17
|
+
get(:_) { arbitrary_success }
|
|
18
|
+
end
|
|
19
|
+
end.to raise_error(described_class::InvalidSequenceError, 'and_yield not called')
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'does not allow calling #and_yield multiple times' do
|
|
23
|
+
expect do
|
|
24
|
+
in_sequence do
|
|
25
|
+
and_yield { arbitrary_success }
|
|
26
|
+
and_yield { arbitrary_success }
|
|
27
|
+
end
|
|
28
|
+
end.to raise_error(described_class::InvalidSequenceError, 'and_yield already called')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'does not allow calling #get after #and_yield' do
|
|
32
|
+
expect do
|
|
33
|
+
in_sequence do
|
|
34
|
+
and_yield { arbitrary_success }
|
|
35
|
+
get(:_) { arbitrary_success }
|
|
36
|
+
end
|
|
37
|
+
end.to raise_error(described_class::InvalidSequenceError, 'and_yield already called')
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it 'does not allow calling #let after #and_yield' do
|
|
41
|
+
expect do
|
|
42
|
+
in_sequence do
|
|
43
|
+
and_yield { arbitrary_success }
|
|
44
|
+
let(:_) { arbitrary_success }
|
|
45
|
+
end
|
|
46
|
+
end.to raise_error(described_class::InvalidSequenceError, 'and_yield already called')
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'does not allow calling #and_then after #and_yield' do
|
|
50
|
+
expect do
|
|
51
|
+
in_sequence do
|
|
52
|
+
and_yield { arbitrary_success }
|
|
53
|
+
and_then { arbitrary_success }
|
|
54
|
+
end
|
|
55
|
+
end.to raise_error(described_class::InvalidSequenceError, 'and_yield already called')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'does not allow calling #observe after #and_yield' do
|
|
59
|
+
expect do
|
|
60
|
+
in_sequence do
|
|
61
|
+
and_yield { arbitrary_success }
|
|
62
|
+
observe { arbitrary_success }
|
|
63
|
+
end
|
|
64
|
+
end.to raise_error(described_class::InvalidSequenceError, 'and_yield already called')
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'requires a block for every operation' do
|
|
68
|
+
expect { in_sequence { get(:_) } }.to raise_error(ArgumentError, 'no block given')
|
|
69
|
+
expect { in_sequence { let(:_) } }.to raise_error(ArgumentError, 'no block given')
|
|
70
|
+
expect { in_sequence { and_then } }.to raise_error(ArgumentError, 'no block given')
|
|
71
|
+
expect { in_sequence { observe } }.to raise_error(ArgumentError, 'no block given')
|
|
72
|
+
expect { in_sequence { and_yield } }.to raise_error(ArgumentError, 'no block given')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context 'when #and_yield succeeds' do
|
|
76
|
+
let(:yielder_result) { Success('yield') }
|
|
77
|
+
before { allow(test_instance).to receive(:yielder).and_return(yielder_result) }
|
|
78
|
+
|
|
79
|
+
it "returns and_yield's result" do
|
|
80
|
+
result = in_sequence do
|
|
81
|
+
and_yield { yielder }
|
|
82
|
+
end
|
|
83
|
+
expect(result).to eq(yielder_result)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'ignores the return value of the #in_sequence block' do
|
|
87
|
+
result = in_sequence do
|
|
88
|
+
and_yield { yielder }
|
|
89
|
+
'a different return value'
|
|
90
|
+
end
|
|
91
|
+
expect(result).to eq(yielder_result)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context 'when #and_yield fails' do
|
|
96
|
+
let(:yielder_result) { Failure('yield') }
|
|
97
|
+
before { allow(test_instance).to receive(:yielder).and_return(yielder_result) }
|
|
98
|
+
|
|
99
|
+
it "returns and_yield's result" do
|
|
100
|
+
result = in_sequence do
|
|
101
|
+
and_yield { yielder }
|
|
102
|
+
end
|
|
103
|
+
expect(result).to eq(yielder_result)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context 'when #get succeeds' do
|
|
108
|
+
let(:getter_result) { Success('get') }
|
|
109
|
+
before { allow(test_instance).to receive(:getter).and_return(getter_result) }
|
|
110
|
+
|
|
111
|
+
it 'its result is available in a subsequent #get' do
|
|
112
|
+
allow(test_instance).to receive(:second_getter).and_return(arbitrary_success)
|
|
113
|
+
|
|
114
|
+
in_sequence do
|
|
115
|
+
get(:get_result) { getter }
|
|
116
|
+
get(:_) { second_getter(get_result) }
|
|
117
|
+
and_yield { arbitrary_success }
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
expect(test_instance).to have_received(:second_getter).with(getter_result.value)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'its result is not available in a previous #get' do
|
|
124
|
+
allow(test_instance).to receive(:second_getter)
|
|
125
|
+
|
|
126
|
+
expect do
|
|
127
|
+
in_sequence do
|
|
128
|
+
get(:_) { second_getter(get_result) }
|
|
129
|
+
get(:get_result) { getter }
|
|
130
|
+
and_yield { arbitrary_success }
|
|
131
|
+
end
|
|
132
|
+
end.to raise_error(NameError)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it 'its result is available in a subsequent #and_then' do
|
|
136
|
+
allow(test_instance).to receive(:and_then_function).and_return(arbitrary_success)
|
|
137
|
+
|
|
138
|
+
in_sequence do
|
|
139
|
+
get(:get_result) { getter }
|
|
140
|
+
and_then { and_then_function(get_result) }
|
|
141
|
+
and_yield { arbitrary_success }
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
expect(test_instance).to have_received(:and_then_function).with(getter_result.value)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
it 'its result is available in a subsequent #observe' do
|
|
148
|
+
allow(test_instance).to receive(:observer)
|
|
149
|
+
|
|
150
|
+
in_sequence do
|
|
151
|
+
get(:get_result) { getter }
|
|
152
|
+
observe { observer(get_result) }
|
|
153
|
+
and_yield { arbitrary_success }
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
expect(test_instance).to have_received(:observer).with(getter_result.value)
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it 'its result is available in #and_yield' do
|
|
160
|
+
allow(test_instance).to receive(:yielder).and_return(arbitrary_success)
|
|
161
|
+
|
|
162
|
+
in_sequence do
|
|
163
|
+
get(:get_result) { getter }
|
|
164
|
+
and_yield { yielder(get_result) }
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
expect(test_instance).to have_received(:yielder).with(getter_result.value)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
context 'when multiple #gets succeed' do
|
|
172
|
+
let(:first_getter_result) { Success('get1') }
|
|
173
|
+
let(:second_getter_result) { Success('get2') }
|
|
174
|
+
|
|
175
|
+
before do
|
|
176
|
+
allow(test_instance).to receive(:first_getter).and_return(first_getter_result)
|
|
177
|
+
allow(test_instance).to receive(:second_getter).and_return(second_getter_result)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it 'both results are available in subsequent operations' do
|
|
181
|
+
allow(test_instance).to receive(:yielder).and_return(arbitrary_success)
|
|
182
|
+
|
|
183
|
+
in_sequence do
|
|
184
|
+
get(:first_get_result) { first_getter }
|
|
185
|
+
get(:second_get_result) { second_getter }
|
|
186
|
+
and_yield { yielder(first_get_result, second_get_result) }
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
expect(test_instance).to have_received(:yielder)
|
|
190
|
+
.with(first_getter_result.value, second_getter_result.value)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
context 'when #get fails' do
|
|
195
|
+
let(:getter_result) { Failure('get') }
|
|
196
|
+
before { allow(test_instance).to receive(:getter).and_return(getter_result) }
|
|
197
|
+
|
|
198
|
+
it 'does not invoke subsequent #gets' do
|
|
199
|
+
allow(test_instance).to receive(:second_getter).and_return(arbitrary_success)
|
|
200
|
+
|
|
201
|
+
in_sequence do
|
|
202
|
+
get(:get_result) { getter }
|
|
203
|
+
get(:_) { second_getter(get_result) }
|
|
204
|
+
and_yield { arbitrary_success }
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
expect(test_instance).not_to have_received(:second_getter)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it 'does not invoke subsequent #and_thens' do
|
|
211
|
+
allow(test_instance).to receive(:and_then_function).and_return(arbitrary_success)
|
|
212
|
+
|
|
213
|
+
in_sequence do
|
|
214
|
+
get(:get_result) { getter }
|
|
215
|
+
and_then { and_then_function(get_result) }
|
|
216
|
+
and_yield { arbitrary_success }
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
expect(test_instance).not_to have_received(:and_then_function)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
it 'does not invoke subsequent #observes' do
|
|
223
|
+
allow(test_instance).to receive(:observer)
|
|
224
|
+
|
|
225
|
+
in_sequence do
|
|
226
|
+
get(:get_result) { getter }
|
|
227
|
+
observe { observer(get_result) }
|
|
228
|
+
and_yield { arbitrary_success }
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
expect(test_instance).not_to have_received(:observer)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
it 'does not invoke #and_yield' do
|
|
235
|
+
allow(test_instance).to receive(:yielder).and_return(arbitrary_success)
|
|
236
|
+
|
|
237
|
+
in_sequence do
|
|
238
|
+
get(:get_result) { getter }
|
|
239
|
+
and_yield { yielder }
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
expect(test_instance).not_to have_received(:yielder)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
it 'returns the failure' do
|
|
246
|
+
result = in_sequence do
|
|
247
|
+
get(:get_result) { getter }
|
|
248
|
+
and_yield { arbitrary_success }
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
expect(result).to eq(getter_result)
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
context 'when #let succeeds' do
|
|
256
|
+
let(:object) { { :a => 'a' } }
|
|
257
|
+
before { allow(test_instance).to receive(:object).and_return(object) }
|
|
258
|
+
|
|
259
|
+
it 'its result is available in a subsequent #let' do
|
|
260
|
+
allow(test_instance).to receive(:test_function)
|
|
261
|
+
|
|
262
|
+
in_sequence do
|
|
263
|
+
let(:a) { object.fetch(:a) }
|
|
264
|
+
let(:_) { test_function(a) }
|
|
265
|
+
and_yield { arbitrary_success }
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
expect(test_instance).to have_received(:test_function).with(object.fetch(:a))
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
it 'its result is available in a subsequent #and_then' do
|
|
272
|
+
allow(test_instance).to receive(:and_then_function).and_return(arbitrary_success)
|
|
273
|
+
|
|
274
|
+
in_sequence do
|
|
275
|
+
let(:a) { object.fetch(:a) }
|
|
276
|
+
and_then { and_then_function(a) }
|
|
277
|
+
and_yield { arbitrary_success }
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
expect(test_instance).to have_received(:and_then_function).with(object.fetch(:a))
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
it 'its result is available in a subsequent #observe' do
|
|
284
|
+
allow(test_instance).to receive(:observer)
|
|
285
|
+
|
|
286
|
+
in_sequence do
|
|
287
|
+
let(:a) { object.fetch(:a) }
|
|
288
|
+
observe { observer(a) }
|
|
289
|
+
and_yield { arbitrary_success }
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
expect(test_instance).to have_received(:observer).with(object.fetch(:a))
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
it 'its result is available in #and_yield' do
|
|
296
|
+
allow(test_instance).to receive(:yielder).and_return(arbitrary_success)
|
|
297
|
+
|
|
298
|
+
in_sequence do
|
|
299
|
+
let(:a) { object.fetch(:a) }
|
|
300
|
+
and_yield { yielder(a) }
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
expect(test_instance).to have_received(:yielder).with(object.fetch(:a))
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
context 'when #let raises an error' do
|
|
308
|
+
let(:object) { { :a => 'a' } }
|
|
309
|
+
before { allow(test_instance).to receive(:object).and_return(object) }
|
|
310
|
+
|
|
311
|
+
it 'bubbles the raised error' do
|
|
312
|
+
expect do
|
|
313
|
+
in_sequence do
|
|
314
|
+
let(:b) { object.fetch(:b) }
|
|
315
|
+
and_yield { arbitrary_success }
|
|
316
|
+
end
|
|
317
|
+
end.to raise_error(KeyError)
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
it 'does not invoke #and_yield' do
|
|
321
|
+
allow(test_instance).to receive(:yielder).and_return(arbitrary_success)
|
|
322
|
+
|
|
323
|
+
begin
|
|
324
|
+
in_sequence do
|
|
325
|
+
let(:b) { object.fetch(:b) }
|
|
326
|
+
and_yield { yielder }
|
|
327
|
+
end
|
|
328
|
+
rescue KeyError
|
|
329
|
+
# Ignore
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
expect(test_instance).not_to have_received(:yielder)
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
context 'when #and_then succeeds' do
|
|
337
|
+
let(:and_then_result) { Success('and_then') }
|
|
338
|
+
before { allow(test_instance).to receive(:and_then_function).and_return(and_then_result) }
|
|
339
|
+
|
|
340
|
+
it 'continues the sequence' do
|
|
341
|
+
allow(test_instance).to receive(:another_step).and_return(arbitrary_success)
|
|
342
|
+
|
|
343
|
+
in_sequence do
|
|
344
|
+
and_then { and_then_function }
|
|
345
|
+
and_then { another_step }
|
|
346
|
+
and_yield { arbitrary_success }
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
expect(test_instance).to have_received(:another_step)
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
context 'when #and_then fails' do
|
|
354
|
+
let(:and_then_result) { Failure('and_then') }
|
|
355
|
+
before { allow(test_instance).to receive(:and_then_function).and_return(and_then_result) }
|
|
356
|
+
|
|
357
|
+
it 'does not continue the sequence' do
|
|
358
|
+
allow(test_instance).to receive(:another_step).and_return(arbitrary_success)
|
|
359
|
+
|
|
360
|
+
in_sequence do
|
|
361
|
+
and_then { and_then_function }
|
|
362
|
+
and_then { another_step }
|
|
363
|
+
and_yield { arbitrary_success }
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
expect(test_instance).not_to have_received(:another_step)
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it 'returns the failure' do
|
|
370
|
+
result = in_sequence do
|
|
371
|
+
and_then { and_then_function }
|
|
372
|
+
and_yield { arbitrary_success }
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
expect(result).to eq(and_then_result)
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
context 'when #observe returns a failure' do
|
|
380
|
+
let(:observe_result) { Failure('observe') }
|
|
381
|
+
before { allow(test_instance).to receive(:observer).and_return(observe_result) }
|
|
382
|
+
|
|
383
|
+
it 'its return value is ignored and the sequence continues' do
|
|
384
|
+
allow(test_instance).to receive(:another_step).and_return(arbitrary_success)
|
|
385
|
+
|
|
386
|
+
in_sequence do
|
|
387
|
+
observe { observer }
|
|
388
|
+
and_then { another_step }
|
|
389
|
+
and_yield { arbitrary_success }
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
expect(test_instance).to have_received(:another_step)
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
it 'does not allow calling methods outside of the wrapped instance' do
|
|
397
|
+
expect do
|
|
398
|
+
in_sequence do
|
|
399
|
+
and_yield { top_level_test_method }
|
|
400
|
+
end
|
|
401
|
+
end.to raise_error(NameError)
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
context 'when including FunctionalLightService::Prelude' do
|
|
405
|
+
let(:test_class) { Class.new { include FunctionalLightService::Prelude } }
|
|
406
|
+
|
|
407
|
+
it '#in_sequence is available' do
|
|
408
|
+
expect do
|
|
409
|
+
in_sequence do
|
|
410
|
+
and_yield { arbitrary_success }
|
|
411
|
+
end
|
|
412
|
+
end.not_to raise_error
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
context 'readme example' do
|
|
417
|
+
let(:test_class) do
|
|
418
|
+
Class.new do
|
|
419
|
+
include FunctionalLightService::Prelude
|
|
420
|
+
|
|
421
|
+
# rubocop:disable Metrics/AbcSize
|
|
422
|
+
def call(input)
|
|
423
|
+
in_sequence do
|
|
424
|
+
get(:sanitized_input) { sanitize(input) }
|
|
425
|
+
and_then { validate(sanitized_input) }
|
|
426
|
+
get(:user) { get_user_from_db(sanitized_input) }
|
|
427
|
+
let(:name) { user.fetch(:name) }
|
|
428
|
+
observe { log('user name', name) }
|
|
429
|
+
get(:request) { build_request(sanitized_input, user) }
|
|
430
|
+
observe { log('sending request', request) }
|
|
431
|
+
get(:response) { send_request(request) }
|
|
432
|
+
observe { log('got response', response) }
|
|
433
|
+
and_yield { format_response(response) }
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
# rubocop:enable Metrics/AbcSize
|
|
437
|
+
|
|
438
|
+
def sanitize(input)
|
|
439
|
+
sanitized_input = input
|
|
440
|
+
Success(sanitized_input)
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
def validate(sanitized_input)
|
|
444
|
+
Success(sanitized_input)
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
def get_user_from_db(sanitized_input)
|
|
448
|
+
Success(:type => :admin, :id => sanitized_input.fetch(:id), :name => 'John')
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
def build_request(sanitized_input, user)
|
|
452
|
+
Success(:input => sanitized_input, :user => user)
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
def log(message, data)
|
|
456
|
+
# logger.info(message, data)
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
def send_request(_request)
|
|
460
|
+
Success(:status => 200)
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
def format_response(response)
|
|
464
|
+
Success(:response => response, :message => 'it worked')
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
it 'returns expected result' do
|
|
470
|
+
result = test_instance.call(:id => 1)
|
|
471
|
+
|
|
472
|
+
expect(result).to eq(Success(
|
|
473
|
+
:response => { :status => 200 },
|
|
474
|
+
:message => 'it worked'
|
|
475
|
+
))
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
it 'logs expected values' do
|
|
479
|
+
allow(test_instance).to receive(:log).and_call_original
|
|
480
|
+
|
|
481
|
+
test_instance.call(:id => 1)
|
|
482
|
+
|
|
483
|
+
expect(test_instance).to have_received(:log)
|
|
484
|
+
.with('user name', 'John')
|
|
485
|
+
.ordered
|
|
486
|
+
expect(test_instance).to have_received(:log)
|
|
487
|
+
.with('sending request',
|
|
488
|
+
:input => { :id => 1 },
|
|
489
|
+
:user => { :type => :admin, :id => 1, :name => 'John' })
|
|
490
|
+
.ordered
|
|
491
|
+
expect(test_instance).to have_received(:log)
|
|
492
|
+
.with('got response', :status => 200)
|
|
493
|
+
.ordered
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
def in_sequence(&block)
|
|
498
|
+
test_instance.instance_eval do
|
|
499
|
+
in_sequence(&block)
|
|
500
|
+
end
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
def top_level_test_method
|
|
505
|
+
:empty
|
|
506
|
+
end
|
|
@@ -1,83 +1,66 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require 'test_doubles'
|
|
3
|
-
|
|
4
|
-
describe FunctionalLightService::LocalizationAdapter do
|
|
5
|
-
let(:action_class) { TestDoubles::AnAction }
|
|
6
|
-
let(:adapter) { described_class.new }
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
subject = adapter.success(message_or_key,
|
|
68
|
-
action_class,
|
|
69
|
-
:i18n_variable => "value")
|
|
70
|
-
|
|
71
|
-
expect(subject).to eq("message")
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
context "when provided a String" do
|
|
76
|
-
let(:message_or_key) { "action failed" }
|
|
77
|
-
|
|
78
|
-
it "returns the message" do
|
|
79
|
-
expect(subject).to eq(message_or_key)
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require 'test_doubles'
|
|
3
|
+
|
|
4
|
+
describe FunctionalLightService::LocalizationAdapter do
|
|
5
|
+
let(:action_class) { TestDoubles::AnAction }
|
|
6
|
+
let(:adapter) { described_class.new }
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
FunctionalLightService::LocalizationMap.instance[:en] = {
|
|
10
|
+
:'test_doubles/an_action' => {
|
|
11
|
+
:light_service => {
|
|
12
|
+
:failures => {
|
|
13
|
+
:not_found => "failure message"
|
|
14
|
+
},
|
|
15
|
+
:successes => {
|
|
16
|
+
:not_found => "success message"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
after do
|
|
24
|
+
FunctionalLightService::LocalizationMap.instance.clear
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "#failure" do
|
|
28
|
+
subject { adapter.failure(message_or_key, action_class) }
|
|
29
|
+
|
|
30
|
+
context "when provided a Symbol" do
|
|
31
|
+
let(:message_or_key) { :not_found }
|
|
32
|
+
|
|
33
|
+
it "translates the message" do
|
|
34
|
+
expect(subject).to eq("failure message")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
context "when provided a String" do
|
|
39
|
+
let(:message_or_key) { "action failed" }
|
|
40
|
+
|
|
41
|
+
it "returns the message" do
|
|
42
|
+
expect(subject).to eq(message_or_key)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe "#success" do
|
|
48
|
+
subject { adapter.success(message_or_key, action_class) }
|
|
49
|
+
|
|
50
|
+
context "when provided a Symbol" do
|
|
51
|
+
let(:message_or_key) { :not_found }
|
|
52
|
+
|
|
53
|
+
it "translates the message" do
|
|
54
|
+
expect(subject).to eq("success message")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "when provided a String" do
|
|
59
|
+
let(:message_or_key) { "action failed" }
|
|
60
|
+
|
|
61
|
+
it "returns the message" do
|
|
62
|
+
expect(subject).to eq(message_or_key)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -16,6 +16,9 @@ if ENV['RUN_COVERAGE_REPORT']
|
|
|
16
16
|
SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
# i18n non e' piu una dipendenza runtime della gem: viene caricata qui
|
|
20
|
+
# per testare l'adapter I18n e la selezione automatica in Configuration
|
|
21
|
+
require "i18n"
|
|
19
22
|
require "functional-light-service"
|
|
20
23
|
require "functional-light-service/testing"
|
|
21
24
|
require "functional-light-service/functional/null"
|
data/spec/test_doubles.rb
CHANGED
|
@@ -599,6 +599,34 @@ module TestDoubles
|
|
|
599
599
|
end
|
|
600
600
|
end
|
|
601
601
|
|
|
602
|
+
class AddsNumbersWithOptionalDefaults
|
|
603
|
+
extend FunctionalLightService::Action
|
|
604
|
+
|
|
605
|
+
expects :first_number
|
|
606
|
+
expects :second_number, :default => ->(ctx) { ctx[:first_number] + 7 }
|
|
607
|
+
expects :third_number, :default => 10
|
|
608
|
+
promises :total
|
|
609
|
+
|
|
610
|
+
executed do |ctx|
|
|
611
|
+
ctx.total = ctx.first_number + ctx.second_number + ctx.third_number
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
class OrganizerWithActionsUsingDefaults
|
|
616
|
+
extend FunctionalLightService::Organizer
|
|
617
|
+
|
|
618
|
+
def self.call
|
|
619
|
+
with(:first_number => 1, :number => 1).reduce(actions)
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
def self.actions
|
|
623
|
+
[
|
|
624
|
+
AddsNumbersWithOptionalDefaults,
|
|
625
|
+
AddToTotalAction
|
|
626
|
+
]
|
|
627
|
+
end
|
|
628
|
+
end
|
|
629
|
+
|
|
602
630
|
class AnOrganizerThatAddsToContext
|
|
603
631
|
extend FunctionalLightService::Organizer
|
|
604
632
|
|