functional-light-service 0.5.4 → 6.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 +4 -4
- data/.github/workflows/project-build.yml +35 -11
- data/.rubocop.yml +101 -160
- data/AUDIT-functional-light-service.md +352 -0
- data/CHANGELOG.md +38 -0
- data/README.md +54 -2
- data/audit/bench.rb +99 -0
- data/audit/verify_findings.rb +172 -0
- data/functional-light-service.gemspec +15 -21
- data/lib/functional-light-service/action.rb +97 -101
- data/lib/functional-light-service/configuration.rb +26 -24
- data/lib/functional-light-service/context/key_verifier.rb +124 -118
- data/lib/functional-light-service/context.rb +63 -20
- data/lib/functional-light-service/deprecations.rb +26 -0
- data/lib/functional-light-service/errors.rb +8 -6
- data/lib/functional-light-service/functional/enum.rb +286 -250
- data/lib/functional-light-service/functional/maybe.rb +21 -15
- data/lib/functional-light-service/functional/monad.rb +77 -66
- data/lib/functional-light-service/functional/null.rb +88 -74
- data/lib/functional-light-service/functional/option.rb +100 -97
- data/lib/functional-light-service/functional/result.rb +129 -116
- data/lib/functional-light-service/localization_adapter.rb +48 -47
- data/lib/functional-light-service/organizer/execute.rb +16 -14
- data/lib/functional-light-service/organizer/iterate.rb +30 -25
- data/lib/functional-light-service/organizer/reduce_if.rb +19 -17
- data/lib/functional-light-service/organizer/reduce_until.rb +22 -20
- data/lib/functional-light-service/organizer/scoped_reducable.rb +15 -13
- data/lib/functional-light-service/organizer/with_callback.rb +28 -26
- data/lib/functional-light-service/organizer/with_reducer.rb +81 -77
- data/lib/functional-light-service/organizer/with_reducer_factory.rb +20 -18
- data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +110 -108
- data/lib/functional-light-service/organizer.rb +114 -114
- data/lib/functional-light-service/testing/context_factory.rb +48 -42
- data/lib/functional-light-service/testing.rb +3 -1
- data/lib/functional-light-service/version.rb +5 -3
- data/lib/functional-light-service.rb +30 -28
- data/spec/acceptance/after_actions_spec.rb +87 -71
- data/spec/acceptance/before_actions_spec.rb +115 -98
- data/spec/acceptance/custom_log_from_organizer_spec.rb +61 -60
- data/spec/acceptance/deprecation_warnings_spec.rb +82 -0
- data/spec/acceptance/fail_spec.rb +52 -50
- data/spec/acceptance/message_localization_spec.rb +119 -118
- data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +68 -65
- data/spec/acceptance/organizer/reduce_if_spec.rb +89 -89
- data/spec/acceptance/organizer/with_callback_spec.rb +113 -110
- data/spec/acceptance/{not_having_call_method_warning_spec.rb → organizer_entry_point_spec.rb} +10 -7
- data/spec/acceptance/rollback_spec.rb +183 -132
- data/spec/action_expects_and_promises_spec.rb +97 -93
- data/spec/action_promised_keys_spec.rb +126 -122
- data/spec/context_spec.rb +289 -197
- data/spec/examples/controller_spec.rb +63 -63
- data/spec/examples/validate_address_spec.rb +38 -37
- data/spec/lib/deterministic/currify_spec.rb +90 -88
- data/spec/lib/deterministic/null_spec.rb +6 -1
- data/spec/lib/deterministic/option_spec.rb +140 -137
- data/spec/lib/deterministic/result/result_map_spec.rb +155 -154
- data/spec/lib/deterministic/result/result_shared.rb +3 -2
- data/spec/lib/deterministic/result_spec.rb +2 -2
- data/spec/lib/edge_cases_spec.rb +156 -0
- data/spec/lib/enum_spec.rb +1 -1
- data/spec/lib/native_pattern_matching_spec.rb +74 -0
- data/spec/organizer_spec.rb +115 -114
- data/spec/readme_spec.rb +45 -47
- data/spec/sample/calculates_order_tax_action_spec.rb +16 -16
- data/spec/sample/calculates_tax_spec.rb +1 -1
- data/spec/sample/looks_up_tax_percentage_action_spec.rb +55 -55
- data/spec/sample/tax/calculates_order_tax_action.rb +10 -9
- data/spec/sample/tax/looks_up_tax_percentage_action.rb +28 -27
- data/spec/sample/tax/provides_free_shipping_action.rb +11 -10
- data/spec/spec_helper.rb +6 -0
- data/spec/test_doubles.rb +628 -599
- data/spec/testing/context_factory_spec.rb +21 -0
- metadata +45 -161
- data/lib/functional-light-service/organizer/verify_call_method_exists.rb +0 -29
- data/spec/acceptance/include_warning_spec.rb +0 -29
data/spec/context_spec.rb
CHANGED
|
@@ -1,197 +1,289 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'test_doubles'
|
|
3
|
-
|
|
4
|
-
RSpec.describe FunctionalLightService::Context do
|
|
5
|
-
let(:context) { FunctionalLightService::Context.make }
|
|
6
|
-
|
|
7
|
-
describe "can be made" do
|
|
8
|
-
context "with no arguments" do
|
|
9
|
-
subject { FunctionalLightService::Context.make }
|
|
10
|
-
it { is_expected.to be_success }
|
|
11
|
-
specify "message is empty string" do
|
|
12
|
-
expect(context.message).to be_empty
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
context "with a hash" do
|
|
17
|
-
it "has the hash values" do
|
|
18
|
-
context = FunctionalLightService::Context.make(:one => 1)
|
|
19
|
-
|
|
20
|
-
expect(context[:one]).to eq(1)
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
context "with FAILURE" do
|
|
25
|
-
it "is failed" do
|
|
26
|
-
outcome = FunctionalLightService::Result::Failure(:message => '', :error => nil)
|
|
27
|
-
context = FunctionalLightService::Context.new({}, outcome)
|
|
28
|
-
|
|
29
|
-
expect(context).to be_failure
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
describe "can't be made" do
|
|
35
|
-
specify "with invalid parameters" do
|
|
36
|
-
expect { FunctionalLightService::Context.make([]) }.to raise_error(ArgumentError)
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it "can be asked for success?" do
|
|
41
|
-
outcome = FunctionalLightService::Result::Success(:message => '', :error => nil)
|
|
42
|
-
context = FunctionalLightService::Context.new({}, outcome)
|
|
43
|
-
|
|
44
|
-
expect(context).to be_success
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it "can be asked for failure?" do
|
|
48
|
-
outcome = FunctionalLightService::Result::Failure(:message => '', :error => nil)
|
|
49
|
-
context = FunctionalLightService::Context.new({}, outcome)
|
|
50
|
-
|
|
51
|
-
expect(context).to be_failure
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it "can be asked for skip_remaining?" do
|
|
55
|
-
context.skip_remaining!
|
|
56
|
-
|
|
57
|
-
expect(context.skip_remaining?).to be_truthy
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
it "can be pushed into a SUCCESS state" do
|
|
61
|
-
context.succeed!("a happy end")
|
|
62
|
-
|
|
63
|
-
expect(context).to be_success
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
it "can be pushed into a SUCCESS state without a message" do
|
|
67
|
-
context.succeed!
|
|
68
|
-
|
|
69
|
-
expect(context).to be_success
|
|
70
|
-
expect(context.message).to be_nil
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
it "can be pushed into a FAILURE state without a message" do
|
|
74
|
-
context.fail!
|
|
75
|
-
|
|
76
|
-
expect(context).to be_failure
|
|
77
|
-
expect(context.message).to be_nil
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
it "can be pushed into a FAILURE state with a message" do
|
|
81
|
-
context.fail!("a sad end")
|
|
82
|
-
|
|
83
|
-
expect(context).to be_failure
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
it "can be pushed into a FAILURE state with a message in an options hash" do
|
|
87
|
-
context.fail!("a sad end")
|
|
88
|
-
|
|
89
|
-
expect(context).to be_failure
|
|
90
|
-
expect(context.message).to eq("a sad end")
|
|
91
|
-
expect(context.error_code).to be_nil
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
it "can be pushed into a FAILURE state with an error code in options hash" do
|
|
95
|
-
context.fail!("a sad end", 10_005)
|
|
96
|
-
|
|
97
|
-
expect(context).to be_failure
|
|
98
|
-
expect(context.message).to eq("a sad end")
|
|
99
|
-
expect(context.error_code).to eq(10_005)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
it "uses localization adapter to translate failure message" do
|
|
103
|
-
action_class = TestDoubles::AnAction
|
|
104
|
-
expect(FunctionalLightService::Configuration.localization_adapter)
|
|
105
|
-
.to receive(:failure)
|
|
106
|
-
.with(:failure_reason, action_class, {})
|
|
107
|
-
.and_return("message")
|
|
108
|
-
|
|
109
|
-
context = FunctionalLightService::Context.make
|
|
110
|
-
context.current_action = action_class
|
|
111
|
-
context.fail!(:failure_reason)
|
|
112
|
-
|
|
113
|
-
expect(context).to be_failure
|
|
114
|
-
expect(context.message).to eq("message")
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
it "uses localization adapter to translate success message" do
|
|
118
|
-
action_class = TestDoubles::AnAction
|
|
119
|
-
expect(FunctionalLightService::Configuration.localization_adapter)
|
|
120
|
-
.to receive(:success)
|
|
121
|
-
.with(:action_passed, action_class, {})
|
|
122
|
-
.and_return("message")
|
|
123
|
-
|
|
124
|
-
context = FunctionalLightService::Context.make
|
|
125
|
-
context.current_action = action_class
|
|
126
|
-
context.succeed!(:action_passed)
|
|
127
|
-
|
|
128
|
-
expect(context).to be_success
|
|
129
|
-
expect(context.message).to eq("message")
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
it "can set a flag to skip all subsequent actions" do
|
|
133
|
-
context.skip_remaining!
|
|
134
|
-
|
|
135
|
-
expect(context).to be_skip_remaining
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
context "stopping additional processing in an action" do
|
|
139
|
-
it "flags processing to stop on failure" do
|
|
140
|
-
context.fail!("on purpose")
|
|
141
|
-
expect(context.stop_processing?).to be_truthy
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
it "flags processing to stop when remaining actions should be skipped" do
|
|
145
|
-
context.skip_remaining!
|
|
146
|
-
expect(context.stop_processing?).to be_truthy
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
it "can fail with FailWithRollBackError" do
|
|
151
|
-
expect { context.fail_with_rollback!("roll me back") }.to \
|
|
152
|
-
raise_error(FunctionalLightService::FailWithRollbackError)
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
it "exptected outcome reader get Success and message empty and error nil" do
|
|
156
|
-
outcome = FunctionalLightService::Result::Success(:message => "", :error => nil)
|
|
157
|
-
expect(context.outcome).to eq(outcome)
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
it "can contain false values" do
|
|
161
|
-
context = FunctionalLightService::Context.make(:foo => false)
|
|
162
|
-
expect(context[:foo]).to eq false
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
it "allows a default value for #fetch" do
|
|
166
|
-
expect(context.fetch(:madeup, :default)).to eq(:default)
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
it "allows a default block value for #fetch" do
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
expect(
|
|
185
|
-
expect(
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'test_doubles'
|
|
3
|
+
|
|
4
|
+
RSpec.describe FunctionalLightService::Context do
|
|
5
|
+
let(:context) { FunctionalLightService::Context.make }
|
|
6
|
+
|
|
7
|
+
describe "can be made" do
|
|
8
|
+
context "with no arguments" do
|
|
9
|
+
subject { FunctionalLightService::Context.make }
|
|
10
|
+
it { is_expected.to be_success }
|
|
11
|
+
specify "message is empty string" do
|
|
12
|
+
expect(context.message).to be_empty
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context "with a hash" do
|
|
17
|
+
it "has the hash values" do
|
|
18
|
+
context = FunctionalLightService::Context.make(:one => 1)
|
|
19
|
+
|
|
20
|
+
expect(context[:one]).to eq(1)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context "with FAILURE" do
|
|
25
|
+
it "is failed" do
|
|
26
|
+
outcome = FunctionalLightService::Result::Failure(:message => '', :error => nil)
|
|
27
|
+
context = FunctionalLightService::Context.new({}, outcome)
|
|
28
|
+
|
|
29
|
+
expect(context).to be_failure
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe "can't be made" do
|
|
35
|
+
specify "with invalid parameters" do
|
|
36
|
+
expect { FunctionalLightService::Context.make([]) }.to raise_error(ArgumentError)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "can be asked for success?" do
|
|
41
|
+
outcome = FunctionalLightService::Result::Success(:message => '', :error => nil)
|
|
42
|
+
context = FunctionalLightService::Context.new({}, outcome)
|
|
43
|
+
|
|
44
|
+
expect(context).to be_success
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "can be asked for failure?" do
|
|
48
|
+
outcome = FunctionalLightService::Result::Failure(:message => '', :error => nil)
|
|
49
|
+
context = FunctionalLightService::Context.new({}, outcome)
|
|
50
|
+
|
|
51
|
+
expect(context).to be_failure
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "can be asked for skip_remaining?" do
|
|
55
|
+
context.skip_remaining!
|
|
56
|
+
|
|
57
|
+
expect(context.skip_remaining?).to be_truthy
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "can be pushed into a SUCCESS state" do
|
|
61
|
+
context.succeed!("a happy end")
|
|
62
|
+
|
|
63
|
+
expect(context).to be_success
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "can be pushed into a SUCCESS state without a message" do
|
|
67
|
+
context.succeed!
|
|
68
|
+
|
|
69
|
+
expect(context).to be_success
|
|
70
|
+
expect(context.message).to be_nil
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "can be pushed into a FAILURE state without a message" do
|
|
74
|
+
context.fail!
|
|
75
|
+
|
|
76
|
+
expect(context).to be_failure
|
|
77
|
+
expect(context.message).to be_nil
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "can be pushed into a FAILURE state with a message" do
|
|
81
|
+
context.fail!("a sad end")
|
|
82
|
+
|
|
83
|
+
expect(context).to be_failure
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "can be pushed into a FAILURE state with a message in an options hash" do
|
|
87
|
+
context.fail!("a sad end")
|
|
88
|
+
|
|
89
|
+
expect(context).to be_failure
|
|
90
|
+
expect(context.message).to eq("a sad end")
|
|
91
|
+
expect(context.error_code).to be_nil
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "can be pushed into a FAILURE state with an error code in options hash" do
|
|
95
|
+
context.fail!("a sad end", 10_005)
|
|
96
|
+
|
|
97
|
+
expect(context).to be_failure
|
|
98
|
+
expect(context.message).to eq("a sad end")
|
|
99
|
+
expect(context.error_code).to eq(10_005)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "uses localization adapter to translate failure message" do
|
|
103
|
+
action_class = TestDoubles::AnAction
|
|
104
|
+
expect(FunctionalLightService::Configuration.localization_adapter)
|
|
105
|
+
.to receive(:failure)
|
|
106
|
+
.with(:failure_reason, action_class, {})
|
|
107
|
+
.and_return("message")
|
|
108
|
+
|
|
109
|
+
context = FunctionalLightService::Context.make
|
|
110
|
+
context.current_action = action_class
|
|
111
|
+
context.fail!(:failure_reason)
|
|
112
|
+
|
|
113
|
+
expect(context).to be_failure
|
|
114
|
+
expect(context.message).to eq("message")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "uses localization adapter to translate success message" do
|
|
118
|
+
action_class = TestDoubles::AnAction
|
|
119
|
+
expect(FunctionalLightService::Configuration.localization_adapter)
|
|
120
|
+
.to receive(:success)
|
|
121
|
+
.with(:action_passed, action_class, {})
|
|
122
|
+
.and_return("message")
|
|
123
|
+
|
|
124
|
+
context = FunctionalLightService::Context.make
|
|
125
|
+
context.current_action = action_class
|
|
126
|
+
context.succeed!(:action_passed)
|
|
127
|
+
|
|
128
|
+
expect(context).to be_success
|
|
129
|
+
expect(context.message).to eq("message")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "can set a flag to skip all subsequent actions" do
|
|
133
|
+
context.skip_remaining!
|
|
134
|
+
|
|
135
|
+
expect(context).to be_skip_remaining
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
context "stopping additional processing in an action" do
|
|
139
|
+
it "flags processing to stop on failure" do
|
|
140
|
+
context.fail!("on purpose")
|
|
141
|
+
expect(context.stop_processing?).to be_truthy
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it "flags processing to stop when remaining actions should be skipped" do
|
|
145
|
+
context.skip_remaining!
|
|
146
|
+
expect(context.stop_processing?).to be_truthy
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "can fail with FailWithRollBackError" do
|
|
151
|
+
expect { context.fail_with_rollback!("roll me back") }.to \
|
|
152
|
+
raise_error(FunctionalLightService::FailWithRollbackError)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
it "exptected outcome reader get Success and message empty and error nil" do
|
|
156
|
+
outcome = FunctionalLightService::Result::Success(:message => "", :error => nil)
|
|
157
|
+
expect(context.outcome).to eq(outcome)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "can contain false values" do
|
|
161
|
+
context = FunctionalLightService::Context.make(:foo => false)
|
|
162
|
+
expect(context[:foo]).to eq false
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "allows a default value for #fetch" do
|
|
166
|
+
expect(context.fetch(:madeup, :default)).to eq(:default)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it "allows a default block value for #fetch" do
|
|
170
|
+
# la forma a blocco e' esattamente cio' che il test verifica
|
|
171
|
+
expect(context.fetch(:madeup) { :default }).to eq(:default) # rubocop:disable Style/RedundantFetchBlock
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
describe "#define_accessor_methods_for_keys" do
|
|
175
|
+
it "raises when a key conflicts with an existing Hash/Context method" do
|
|
176
|
+
expect { context.define_accessor_methods_for_keys([:size]) }
|
|
177
|
+
.to raise_error(FunctionalLightService::ReservedKeysInContextError, /:size conflicts/)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "does not raise when re-defining accessors for the same key" do
|
|
181
|
+
ctx = FunctionalLightService::Context.make(:number => 1)
|
|
182
|
+
ctx.define_accessor_methods_for_keys([:number])
|
|
183
|
+
|
|
184
|
+
expect { ctx.define_accessor_methods_for_keys([:number]) }.not_to raise_error
|
|
185
|
+
expect(ctx.number).to eq(1)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
describe "reserved keys" do
|
|
190
|
+
it "rejects infrastructure keys in expects/promises" do
|
|
191
|
+
action = Class.new do
|
|
192
|
+
extend FunctionalLightService::Action
|
|
193
|
+
|
|
194
|
+
expects :_before_actions
|
|
195
|
+
executed { |_ctx| } # rubocop:disable Lint/EmptyBlock
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
expect { action.execute(:_before_actions => []) }
|
|
199
|
+
.to raise_error(FunctionalLightService::ReservedKeysInContextError)
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
describe "#fail! does not mutate the caller's options hash" do
|
|
204
|
+
it "leaves :error_code in the original hash" do
|
|
205
|
+
options = { :error_code => 500 }
|
|
206
|
+
context.fail!("boom", options)
|
|
207
|
+
|
|
208
|
+
expect(options).to eq(:error_code => 500)
|
|
209
|
+
expect(context.error_code).to eq(500)
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
describe "#reset_skip_remaining!" do
|
|
214
|
+
it "clears the flag but keeps the outcome and its message" do
|
|
215
|
+
context.skip_remaining!("No need to process")
|
|
216
|
+
context.reset_skip_remaining!
|
|
217
|
+
|
|
218
|
+
expect(context.skip_remaining?).to be(false)
|
|
219
|
+
expect(context).to be_success
|
|
220
|
+
expect(context.message).to eq("No need to process")
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
describe "#fetch honours the Hash#fetch contract" do
|
|
225
|
+
it "raises KeyError for a missing key without default" do
|
|
226
|
+
expect { context.fetch(:madeup) }.to raise_error(KeyError)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it "does not write to the context when a default is used" do
|
|
230
|
+
context.fetch(:madeup, :default)
|
|
231
|
+
context.fetch(:another_madeup) { :default } # rubocop:disable Style/RedundantFetchBlock
|
|
232
|
+
|
|
233
|
+
expect(context.to_h).not_to have_key(:madeup)
|
|
234
|
+
expect(context.to_h).not_to have_key(:another_madeup)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it "returns existing falsy values instead of the default" do
|
|
238
|
+
context = FunctionalLightService::Context.make(:flag => false)
|
|
239
|
+
|
|
240
|
+
expect(context.fetch(:flag, true)).to eq(false)
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
context "when aliases are included via .make" do
|
|
245
|
+
let(:context) do
|
|
246
|
+
FunctionalLightService::Context.make(
|
|
247
|
+
:foo => "foobar",
|
|
248
|
+
:foo2 => false,
|
|
249
|
+
:_aliases => aliases
|
|
250
|
+
)
|
|
251
|
+
end
|
|
252
|
+
let(:aliases) { { :foo => :bar, :foo2 => :bar2 } }
|
|
253
|
+
|
|
254
|
+
it "contains the aliases" do
|
|
255
|
+
expect(context.aliases).to eq(aliases)
|
|
256
|
+
expect(context).to include(:foo, :bar)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
it "returns the correct values for #[] and #fetch" do
|
|
260
|
+
expect(context[:bar]).to eq context[:foo]
|
|
261
|
+
expect(context.fetch(:bar)).to eq context[:foo]
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
it "can contain false values" do
|
|
265
|
+
expect(context[:bar2]).to eq false
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
it "resolves aliases on writes too, symmetrically with reads" do
|
|
269
|
+
context[:bar] = "updated"
|
|
270
|
+
|
|
271
|
+
expect(context[:bar]).to eq("updated")
|
|
272
|
+
expect(context[:foo]).to eq("updated")
|
|
273
|
+
# nessuna chiave duplicata: l'alias e' un nome alternativo, non una copia
|
|
274
|
+
expect(context.to_h).not_to have_key(:bar)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
it "resolves aliases in #key? and friends" do
|
|
278
|
+
expect(context.key?(:bar)).to be(true)
|
|
279
|
+
expect(context.has_key?(:bar)).to be(true) # rubocop:disable Style/PreferredHashMethods
|
|
280
|
+
expect(context.member?(:bar)).to be(true)
|
|
281
|
+
expect(context.include?(:bar)).to be(true)
|
|
282
|
+
expect(context.key?(:madeup)).to be(false)
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
it "resolves aliases in #fetch with defaults" do
|
|
286
|
+
expect(context.fetch(:bar, :default)).to eq("foobar")
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
module FunctionalLightService
|
|
4
|
-
module Procify
|
|
5
|
-
def py(m, *args)
|
|
6
|
-
args.
|
|
7
|
-
end
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
class BookingController
|
|
12
|
-
include FunctionalLightService::Prelude::Result
|
|
13
|
-
include FunctionalLightService::Procify
|
|
14
|
-
|
|
15
|
-
Context = Struct.new(:booking, :ability, :format)
|
|
16
|
-
|
|
17
|
-
def index(id, format = :html)
|
|
18
|
-
get_booking(id) << log(:booking) >>
|
|
19
|
-
py(:ability) << log(:ability) >>
|
|
20
|
-
py(:present, format) << log(:presenter) >>
|
|
21
|
-
py(:render) << log(:render)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def log(step)
|
|
25
|
-
->(data) { [step, data] }
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def ability(ctx)
|
|
29
|
-
ctx.ability = {} # Ability.new(@booking)
|
|
30
|
-
Success(ctx)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def present(format, ctx)
|
|
34
|
-
ctx.format = format
|
|
35
|
-
|
|
36
|
-
Success(ctx)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def render(ctx)
|
|
40
|
-
send(ctx.format, ctx)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def html(ctx)
|
|
44
|
-
Success(ctx)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def get_booking(id)
|
|
48
|
-
ctx = Context.new
|
|
49
|
-
ctx.booking = { :ref_anixe => id }
|
|
50
|
-
Success(ctx)
|
|
51
|
-
# @booking = @bms.booking_by_id(id)
|
|
52
|
-
# rescue BSON::InvalidObjectId => ex
|
|
53
|
-
# @booking = nil
|
|
54
|
-
# @ui.error(404, ex.message)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
describe BookingController do
|
|
59
|
-
it "does something" do
|
|
60
|
-
bc = BookingController.new
|
|
61
|
-
bc.index('1234', :html)
|
|
62
|
-
end
|
|
63
|
-
end
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module FunctionalLightService
|
|
4
|
+
module Procify
|
|
5
|
+
def py(m, *args)
|
|
6
|
+
args.any? ? method(m).to_proc.curry[*args] : method(m)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class BookingController
|
|
12
|
+
include FunctionalLightService::Prelude::Result
|
|
13
|
+
include FunctionalLightService::Procify
|
|
14
|
+
|
|
15
|
+
Context = Struct.new(:booking, :ability, :format)
|
|
16
|
+
|
|
17
|
+
def index(id, format = :html)
|
|
18
|
+
get_booking(id) << log(:booking) >>
|
|
19
|
+
py(:ability) << log(:ability) >>
|
|
20
|
+
py(:present, format) << log(:presenter) >>
|
|
21
|
+
py(:render) << log(:render)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def log(step)
|
|
25
|
+
->(data) { [step, data] }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def ability(ctx)
|
|
29
|
+
ctx.ability = {} # Ability.new(@booking)
|
|
30
|
+
Success(ctx)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def present(format, ctx)
|
|
34
|
+
ctx.format = format
|
|
35
|
+
|
|
36
|
+
Success(ctx)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def render(ctx)
|
|
40
|
+
send(ctx.format, ctx)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def html(ctx)
|
|
44
|
+
Success(ctx)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def get_booking(id)
|
|
48
|
+
ctx = Context.new
|
|
49
|
+
ctx.booking = { :ref_anixe => id }
|
|
50
|
+
Success(ctx)
|
|
51
|
+
# @booking = @bms.booking_by_id(id)
|
|
52
|
+
# rescue BSON::InvalidObjectId => ex
|
|
53
|
+
# @booking = nil
|
|
54
|
+
# @ui.error(404, ex.message)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe BookingController do
|
|
59
|
+
it "does something" do
|
|
60
|
+
bc = BookingController.new
|
|
61
|
+
bc.index('1234', :html)
|
|
62
|
+
end
|
|
63
|
+
end
|