functional-light-service 6.1.0 → 6.3.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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/lib/functional-light-service.rb +6 -31
  3. metadata +15 -297
  4. data/.github/workflows/project-build.yml +0 -71
  5. data/.gitignore +0 -22
  6. data/.rspec +0 -3
  7. data/.rubocop.yml +0 -101
  8. data/.solargraph.yml +0 -11
  9. data/AUDIT-functional-light-service.md +0 -352
  10. data/Appraisals +0 -7
  11. data/CHANGELOG.md +0 -273
  12. data/CODE_OF_CONDUCT.md +0 -22
  13. data/Gemfile +0 -4
  14. data/LICENSE +0 -22
  15. data/README.md +0 -1578
  16. data/Rakefile +0 -12
  17. data/VERSION +0 -1
  18. data/audit/bench.rb +0 -99
  19. data/audit/verify_findings.rb +0 -172
  20. data/functional-light-service.gemspec +0 -33
  21. data/gemfiles/dry_inflector_0_2_1.gemfile +0 -5
  22. data/gemfiles/i18n_1_8_11.gemfile +0 -5
  23. data/lib/functional-light-service/action.rb +0 -97
  24. data/lib/functional-light-service/configuration.rb +0 -26
  25. data/lib/functional-light-service/context/key_verifier.rb +0 -124
  26. data/lib/functional-light-service/context.rb +0 -195
  27. data/lib/functional-light-service/deprecations.rb +0 -26
  28. data/lib/functional-light-service/errors.rb +0 -8
  29. data/lib/functional-light-service/functional/enum.rb +0 -286
  30. data/lib/functional-light-service/functional/maybe.rb +0 -21
  31. data/lib/functional-light-service/functional/monad.rb +0 -77
  32. data/lib/functional-light-service/functional/null.rb +0 -88
  33. data/lib/functional-light-service/functional/option.rb +0 -100
  34. data/lib/functional-light-service/functional/result.rb +0 -129
  35. data/lib/functional-light-service/functional/sequencer.rb +0 -144
  36. data/lib/functional-light-service/localization_adapter.rb +0 -48
  37. data/lib/functional-light-service/organizer/execute.rb +0 -16
  38. data/lib/functional-light-service/organizer/iterate.rb +0 -30
  39. data/lib/functional-light-service/organizer/reduce_if.rb +0 -19
  40. data/lib/functional-light-service/organizer/reduce_until.rb +0 -22
  41. data/lib/functional-light-service/organizer/scoped_reducable.rb +0 -15
  42. data/lib/functional-light-service/organizer/with_callback.rb +0 -28
  43. data/lib/functional-light-service/organizer/with_reducer.rb +0 -81
  44. data/lib/functional-light-service/organizer/with_reducer_factory.rb +0 -20
  45. data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +0 -110
  46. data/lib/functional-light-service/organizer.rb +0 -114
  47. data/lib/functional-light-service/testing/context_factory.rb +0 -48
  48. data/lib/functional-light-service/testing.rb +0 -3
  49. data/lib/functional-light-service/version.rb +0 -5
  50. data/resources/fail_actions.png +0 -0
  51. data/resources/light-service.png +0 -0
  52. data/resources/organizer_and_actions.png +0 -0
  53. data/resources/skip_actions.png +0 -0
  54. data/spec/acceptance/add_numbers_spec.rb +0 -11
  55. data/spec/acceptance/after_actions_spec.rb +0 -87
  56. data/spec/acceptance/around_each_spec.rb +0 -19
  57. data/spec/acceptance/before_actions_spec.rb +0 -115
  58. data/spec/acceptance/custom_log_from_organizer_spec.rb +0 -61
  59. data/spec/acceptance/deprecation_warnings_spec.rb +0 -82
  60. data/spec/acceptance/fail_spec.rb +0 -52
  61. data/spec/acceptance/log_from_organizer_spec.rb +0 -154
  62. data/spec/acceptance/message_localization_spec.rb +0 -119
  63. data/spec/acceptance/organizer/add_aliases_spec.rb +0 -28
  64. data/spec/acceptance/organizer/add_to_context_spec.rb +0 -30
  65. data/spec/acceptance/organizer/around_each_with_reduce_if_spec.rb +0 -42
  66. data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +0 -68
  67. data/spec/acceptance/organizer/execute_spec.rb +0 -46
  68. data/spec/acceptance/organizer/iterate_spec.rb +0 -44
  69. data/spec/acceptance/organizer/reduce_if_spec.rb +0 -89
  70. data/spec/acceptance/organizer/reduce_until_spec.rb +0 -49
  71. data/spec/acceptance/organizer/with_callback_spec.rb +0 -113
  72. data/spec/acceptance/organizer_entry_point_spec.rb +0 -35
  73. data/spec/acceptance/rollback_spec.rb +0 -183
  74. data/spec/acceptance/testing/context_factory_spec.rb +0 -54
  75. data/spec/action_expected_keys_spec.rb +0 -63
  76. data/spec/action_expects_and_promises_spec.rb +0 -97
  77. data/spec/action_promised_keys_spec.rb +0 -126
  78. data/spec/action_spec.rb +0 -97
  79. data/spec/context/inspect_spec.rb +0 -42
  80. data/spec/context_spec.rb +0 -289
  81. data/spec/examples/amount_spec.rb +0 -77
  82. data/spec/examples/controller_spec.rb +0 -63
  83. data/spec/examples/validate_address_spec.rb +0 -38
  84. data/spec/lib/deterministic/class_mixin_spec.rb +0 -24
  85. data/spec/lib/deterministic/currify_spec.rb +0 -90
  86. data/spec/lib/deterministic/monad_axioms.rb +0 -46
  87. data/spec/lib/deterministic/monad_spec.rb +0 -47
  88. data/spec/lib/deterministic/null_spec.rb +0 -65
  89. data/spec/lib/deterministic/option_spec.rb +0 -140
  90. data/spec/lib/deterministic/result/failure_spec.rb +0 -65
  91. data/spec/lib/deterministic/result/result_map_spec.rb +0 -155
  92. data/spec/lib/deterministic/result/result_shared.rb +0 -25
  93. data/spec/lib/deterministic/result/success_spec.rb +0 -41
  94. data/spec/lib/deterministic/result_spec.rb +0 -63
  95. data/spec/lib/deterministic/sequencer_spec.rb +0 -506
  96. data/spec/lib/edge_cases_spec.rb +0 -156
  97. data/spec/lib/enum_spec.rb +0 -114
  98. data/spec/lib/native_pattern_matching_spec.rb +0 -74
  99. data/spec/localization_adapter_spec.rb +0 -83
  100. data/spec/organizer/with_reducer_spec.rb +0 -56
  101. data/spec/organizer_key_aliases_spec.rb +0 -29
  102. data/spec/organizer_spec.rb +0 -115
  103. data/spec/readme_spec.rb +0 -45
  104. data/spec/sample/calculates_order_tax_action_spec.rb +0 -16
  105. data/spec/sample/calculates_tax_spec.rb +0 -30
  106. data/spec/sample/looks_up_tax_percentage_action_spec.rb +0 -55
  107. data/spec/sample/provides_free_shipping_action_spec.rb +0 -25
  108. data/spec/sample/tax/calculates_order_tax_action.rb +0 -10
  109. data/spec/sample/tax/calculates_tax.rb +0 -11
  110. data/spec/sample/tax/looks_up_tax_percentage_action.rb +0 -28
  111. data/spec/sample/tax/provides_free_shipping_action.rb +0 -11
  112. data/spec/spec_helper.rb +0 -29
  113. data/spec/support.rb +0 -1
  114. data/spec/test_doubles.rb +0 -628
  115. data/spec/testing/context_factory/iterate_spec.rb +0 -39
  116. data/spec/testing/context_factory/reduce_if_spec.rb +0 -40
  117. data/spec/testing/context_factory/reduce_until_spec.rb +0 -40
  118. data/spec/testing/context_factory/with_callback_spec.rb +0 -38
  119. data/spec/testing/context_factory_spec.rb +0 -76
@@ -1,41 +0,0 @@
1
- require 'spec_helper'
2
- require_relative '../monad_axioms'
3
- require_relative 'result_shared'
4
-
5
- describe FunctionalLightService::Result::Success do
6
- include FunctionalLightService::Prelude::Result
7
-
8
- it_behaves_like 'a Monad' do
9
- let(:monad) { described_class }
10
- end
11
-
12
- subject { described_class.new(1) }
13
-
14
- specify { expect(subject).to be_an_instance_of described_class }
15
- specify { expect(subject).to be_success }
16
- specify { expect(subject).not_to be_failure }
17
- specify { expect(subject.success?).to be_truthy }
18
- specify { expect(subject.failure?).to be_falsey }
19
-
20
- specify { expect(subject).to be_an_instance_of described_class }
21
- specify { expect(subject).to eq(described_class.new(1)) }
22
- specify { expect(subject.fmap { |v| v + 1 }).to eq Success(2) }
23
- specify { expect(subject.map { |v| Failure(v + 1) }).to eq Failure(2) }
24
- specify { expect(subject.map_err { |v| Failure(v + 1) }).to eq Success(1) }
25
-
26
- specify do
27
- expect(subject.pipe { |r| raise RuntimeError unless r == Success(1) }).to eq Success(1)
28
- end
29
-
30
- specify { expect(subject.or(Success(2))).to eq Success(1) }
31
- specify { expect(subject.or_else { Success(2) }).to eq Success(1) }
32
-
33
- specify { expect(subject.and(Success(2))).to eq Success(2) }
34
- specify { expect(subject.and(Failure(2))).to eq Failure(2) }
35
- specify { expect(subject.and_then { Success(2) }).to eq Success(2) }
36
- specify { expect(subject.and_then { Failure(2) }).to eq Failure(2) }
37
-
38
- it_behaves_like 'Result' do
39
- let(:result) { described_class }
40
- end
41
- end
@@ -1,63 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe FunctionalLightService::Result do
4
- include FunctionalLightService::Prelude::Result
5
-
6
- it "can't call Result#new directly" do
7
- # il formato del messaggio NoMethodError cambia tra le versioni di Ruby
8
- expect { described_class.new(1) }.to raise_error(NoMethodError, /private method [`']new'/)
9
- end
10
-
11
- it "fmap" do
12
- expect(Success(1).fmap { |n| n + 1 }).to eq Success(2)
13
- expect(Failure(0).fmap { |n| n + 1 }).to eq Failure(1)
14
- end
15
-
16
- it "map" do
17
- expect(Success(1).map { |n| Success(n + 1) }).to eq Success(2)
18
- expect(Failure(0).map { |n| Success(n + 1) }).to eq Failure(0)
19
- end
20
-
21
- it "+" do
22
- expect(Success([1]) + Failure([2])).to eq Failure([2])
23
- expect(Success(1) + Success(1)).to eq Success(2)
24
- expect(Failure(2) + Success(1)).to eq Failure(2)
25
- expect(Failure([2]) + Failure([3]) + Success(1)).to eq Failure([2, 3])
26
- expect(Success([1]) + Success([1])).to eq Success([1, 1])
27
- expect { Success([1]) + Success(1) }.to raise_error TypeError
28
- end
29
-
30
- subject { Success(1) }
31
- # specify { expect(subject).to be_an_instance_of described_class }
32
- specify { expect(subject).to be_success }
33
- specify { expect(subject).not_to be_failure }
34
- specify { expect(subject.success?).to be_truthy }
35
- specify { expect(subject.failure?).to be_falsey }
36
-
37
- specify { expect(subject).to be_a described_class }
38
- # specify { expect(subject).to eq(described_class.new(1)) }
39
- specify { expect(subject.fmap { |v| v + 1 }).to eq Success(2) }
40
- specify { expect(subject.map { |v| Failure(v + 1) }).to eq Failure(2) }
41
- specify { expect(subject.map_err { |v| Failure(v + 1) }).to eq Success(1) }
42
-
43
- specify do
44
- expect(subject.pipe do |r|
45
- raise RuntimeError unless r == Success(1)
46
- end).to eq Success(1)
47
- end
48
-
49
- specify { expect(subject.or(Success(2))).to eq Success(1) }
50
- specify { expect(subject.or_else { Success(2) }).to eq Success(1) }
51
-
52
- specify { expect(subject.and(Success(2))).to eq Success(2) }
53
- specify { expect(subject.and(Failure(2))).to eq Failure(2) }
54
- specify { expect(subject.and_then { Success(2) }).to eq Success(2) }
55
- specify { expect(subject.and_then { Failure(2) }).to eq Failure(2) }
56
-
57
- it "try!" do
58
- expect(described_class.try! { 1 }).to eq Success(1)
59
- expect(described_class.try! { raise "error" }.inspect).to \
60
- eq Failure(RuntimeError.new("error")).inspect
61
- end
62
- end
63
-
@@ -1,506 +0,0 @@
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