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.
- checksums.yaml +4 -4
- data/lib/functional-light-service.rb +6 -31
- metadata +15 -297
- data/.github/workflows/project-build.yml +0 -71
- data/.gitignore +0 -22
- data/.rspec +0 -3
- data/.rubocop.yml +0 -101
- data/.solargraph.yml +0 -11
- data/AUDIT-functional-light-service.md +0 -352
- data/Appraisals +0 -7
- data/CHANGELOG.md +0 -273
- data/CODE_OF_CONDUCT.md +0 -22
- data/Gemfile +0 -4
- data/LICENSE +0 -22
- data/README.md +0 -1578
- data/Rakefile +0 -12
- data/VERSION +0 -1
- data/audit/bench.rb +0 -99
- data/audit/verify_findings.rb +0 -172
- data/functional-light-service.gemspec +0 -33
- data/gemfiles/dry_inflector_0_2_1.gemfile +0 -5
- data/gemfiles/i18n_1_8_11.gemfile +0 -5
- data/lib/functional-light-service/action.rb +0 -97
- data/lib/functional-light-service/configuration.rb +0 -26
- data/lib/functional-light-service/context/key_verifier.rb +0 -124
- data/lib/functional-light-service/context.rb +0 -195
- data/lib/functional-light-service/deprecations.rb +0 -26
- data/lib/functional-light-service/errors.rb +0 -8
- data/lib/functional-light-service/functional/enum.rb +0 -286
- data/lib/functional-light-service/functional/maybe.rb +0 -21
- data/lib/functional-light-service/functional/monad.rb +0 -77
- data/lib/functional-light-service/functional/null.rb +0 -88
- data/lib/functional-light-service/functional/option.rb +0 -100
- data/lib/functional-light-service/functional/result.rb +0 -129
- data/lib/functional-light-service/functional/sequencer.rb +0 -144
- data/lib/functional-light-service/localization_adapter.rb +0 -48
- data/lib/functional-light-service/organizer/execute.rb +0 -16
- data/lib/functional-light-service/organizer/iterate.rb +0 -30
- data/lib/functional-light-service/organizer/reduce_if.rb +0 -19
- data/lib/functional-light-service/organizer/reduce_until.rb +0 -22
- data/lib/functional-light-service/organizer/scoped_reducable.rb +0 -15
- data/lib/functional-light-service/organizer/with_callback.rb +0 -28
- data/lib/functional-light-service/organizer/with_reducer.rb +0 -81
- data/lib/functional-light-service/organizer/with_reducer_factory.rb +0 -20
- data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +0 -110
- data/lib/functional-light-service/organizer.rb +0 -114
- data/lib/functional-light-service/testing/context_factory.rb +0 -48
- data/lib/functional-light-service/testing.rb +0 -3
- data/lib/functional-light-service/version.rb +0 -5
- data/resources/fail_actions.png +0 -0
- data/resources/light-service.png +0 -0
- data/resources/organizer_and_actions.png +0 -0
- data/resources/skip_actions.png +0 -0
- data/spec/acceptance/add_numbers_spec.rb +0 -11
- data/spec/acceptance/after_actions_spec.rb +0 -87
- data/spec/acceptance/around_each_spec.rb +0 -19
- data/spec/acceptance/before_actions_spec.rb +0 -115
- data/spec/acceptance/custom_log_from_organizer_spec.rb +0 -61
- data/spec/acceptance/deprecation_warnings_spec.rb +0 -82
- data/spec/acceptance/fail_spec.rb +0 -52
- data/spec/acceptance/log_from_organizer_spec.rb +0 -154
- data/spec/acceptance/message_localization_spec.rb +0 -119
- data/spec/acceptance/organizer/add_aliases_spec.rb +0 -28
- data/spec/acceptance/organizer/add_to_context_spec.rb +0 -30
- data/spec/acceptance/organizer/around_each_with_reduce_if_spec.rb +0 -42
- data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +0 -68
- data/spec/acceptance/organizer/execute_spec.rb +0 -46
- data/spec/acceptance/organizer/iterate_spec.rb +0 -44
- data/spec/acceptance/organizer/reduce_if_spec.rb +0 -89
- data/spec/acceptance/organizer/reduce_until_spec.rb +0 -49
- data/spec/acceptance/organizer/with_callback_spec.rb +0 -113
- data/spec/acceptance/organizer_entry_point_spec.rb +0 -35
- data/spec/acceptance/rollback_spec.rb +0 -183
- data/spec/acceptance/testing/context_factory_spec.rb +0 -54
- data/spec/action_expected_keys_spec.rb +0 -63
- data/spec/action_expects_and_promises_spec.rb +0 -97
- data/spec/action_promised_keys_spec.rb +0 -126
- data/spec/action_spec.rb +0 -97
- data/spec/context/inspect_spec.rb +0 -42
- data/spec/context_spec.rb +0 -289
- data/spec/examples/amount_spec.rb +0 -77
- data/spec/examples/controller_spec.rb +0 -63
- data/spec/examples/validate_address_spec.rb +0 -38
- data/spec/lib/deterministic/class_mixin_spec.rb +0 -24
- data/spec/lib/deterministic/currify_spec.rb +0 -90
- data/spec/lib/deterministic/monad_axioms.rb +0 -46
- data/spec/lib/deterministic/monad_spec.rb +0 -47
- data/spec/lib/deterministic/null_spec.rb +0 -65
- data/spec/lib/deterministic/option_spec.rb +0 -140
- data/spec/lib/deterministic/result/failure_spec.rb +0 -65
- data/spec/lib/deterministic/result/result_map_spec.rb +0 -155
- data/spec/lib/deterministic/result/result_shared.rb +0 -25
- data/spec/lib/deterministic/result/success_spec.rb +0 -41
- data/spec/lib/deterministic/result_spec.rb +0 -63
- data/spec/lib/deterministic/sequencer_spec.rb +0 -506
- data/spec/lib/edge_cases_spec.rb +0 -156
- data/spec/lib/enum_spec.rb +0 -114
- data/spec/lib/native_pattern_matching_spec.rb +0 -74
- data/spec/localization_adapter_spec.rb +0 -83
- data/spec/organizer/with_reducer_spec.rb +0 -56
- data/spec/organizer_key_aliases_spec.rb +0 -29
- data/spec/organizer_spec.rb +0 -115
- data/spec/readme_spec.rb +0 -45
- data/spec/sample/calculates_order_tax_action_spec.rb +0 -16
- data/spec/sample/calculates_tax_spec.rb +0 -30
- data/spec/sample/looks_up_tax_percentage_action_spec.rb +0 -55
- data/spec/sample/provides_free_shipping_action_spec.rb +0 -25
- data/spec/sample/tax/calculates_order_tax_action.rb +0 -10
- data/spec/sample/tax/calculates_tax.rb +0 -11
- data/spec/sample/tax/looks_up_tax_percentage_action.rb +0 -28
- data/spec/sample/tax/provides_free_shipping_action.rb +0 -11
- data/spec/spec_helper.rb +0 -29
- data/spec/support.rb +0 -1
- data/spec/test_doubles.rb +0 -628
- data/spec/testing/context_factory/iterate_spec.rb +0 -39
- data/spec/testing/context_factory/reduce_if_spec.rb +0 -40
- data/spec/testing/context_factory/reduce_until_spec.rb +0 -40
- data/spec/testing/context_factory/with_callback_spec.rb +0 -38
- data/spec/testing/context_factory_spec.rb +0 -76
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module FunctionalLightService
|
|
4
|
-
module Organizer
|
|
5
|
-
class WithReducerLogDecorator
|
|
6
|
-
attr_reader :logged, :logger, :decorated, :organizer
|
|
7
|
-
|
|
8
|
-
alias logged? logged
|
|
9
|
-
|
|
10
|
-
def initialize(organizer, logger:, decorated: WithReducer.new)
|
|
11
|
-
@decorated = decorated
|
|
12
|
-
@organizer = organizer
|
|
13
|
-
|
|
14
|
-
decorated.organizer = organizer
|
|
15
|
-
|
|
16
|
-
@logger = logger
|
|
17
|
-
@logged = false
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def with(data = {})
|
|
21
|
-
logger.info { "[FunctionalLightService] - calling organizer <#{organizer}>" }
|
|
22
|
-
|
|
23
|
-
decorated.with(data)
|
|
24
|
-
|
|
25
|
-
logger.info do
|
|
26
|
-
"[FunctionalLightService] - keys in context: " \
|
|
27
|
-
"#{extract_keys(decorated.context.keys)}"
|
|
28
|
-
end
|
|
29
|
-
self
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def around_each(handler)
|
|
33
|
-
decorated.around_each(handler)
|
|
34
|
-
self
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def reduce(*actions)
|
|
38
|
-
decorated.reduce(*actions) do |context, action|
|
|
39
|
-
next context if logged?
|
|
40
|
-
|
|
41
|
-
if has_failure?(context)
|
|
42
|
-
write_failure_log(context, action)
|
|
43
|
-
next context
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
if skip_remaining?(context)
|
|
47
|
-
write_skip_remaining_log(context, action)
|
|
48
|
-
next context
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
write_log(action, context)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
private
|
|
56
|
-
|
|
57
|
-
def write_log(action, context)
|
|
58
|
-
return unless logger.info?
|
|
59
|
-
|
|
60
|
-
logger.info("[FunctionalLightService] - executing <#{action}>")
|
|
61
|
-
log_expects(action)
|
|
62
|
-
log_promises(action)
|
|
63
|
-
logger.info("[FunctionalLightService] - keys in context: "\
|
|
64
|
-
"#{extract_keys(context.keys)}")
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def log_expects(action)
|
|
68
|
-
return unless defined?(action.expects) && action.expects.any?
|
|
69
|
-
|
|
70
|
-
logger.info("[FunctionalLightService] - expects: " \
|
|
71
|
-
"#{extract_keys(action.expects)}")
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def log_promises(action)
|
|
75
|
-
return unless defined?(action.promises) && action.promises.any?
|
|
76
|
-
|
|
77
|
-
logger.info("[FunctionalLightService] - promises: " \
|
|
78
|
-
"#{extract_keys(action.promises)}")
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def extract_keys(keys)
|
|
82
|
-
keys.map { |key| ":#{key}" }.join(', ')
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def has_failure?(context)
|
|
86
|
-
context.respond_to?(:failure?) && context.failure?
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def write_failure_log(context, action)
|
|
90
|
-
logger.warn("[FunctionalLightService] - :-((( <#{action}> has failed...")
|
|
91
|
-
logger.warn("[FunctionalLightService] - context message: #{context.message}")
|
|
92
|
-
@logged = true
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def skip_remaining?(context)
|
|
96
|
-
context.respond_to?(:skip_remaining?) && context.skip_remaining?
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def write_skip_remaining_log(context, action)
|
|
100
|
-
return unless logger.info?
|
|
101
|
-
|
|
102
|
-
msg = "[FunctionalLightService] - ;-) <#{action}> has decided " \
|
|
103
|
-
"to skip the rest of the actions"
|
|
104
|
-
logger.info(msg)
|
|
105
|
-
logger.info("[FunctionalLightService] - context message: #{context.message}")
|
|
106
|
-
@logged = true
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module FunctionalLightService
|
|
4
|
-
module Organizer
|
|
5
|
-
def self.extended(base_class)
|
|
6
|
-
base_class.extend ClassMethods
|
|
7
|
-
base_class.extend Macros
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def self.included(base_class)
|
|
11
|
-
FunctionalLightService::Deprecations.warn(
|
|
12
|
-
"Including FunctionalLightService::Organizer is deprecated; " \
|
|
13
|
-
"use `extend FunctionalLightService::Organizer` instead"
|
|
14
|
-
)
|
|
15
|
-
extended(base_class)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# In case this module is included
|
|
19
|
-
module ClassMethods
|
|
20
|
-
def with(data = {})
|
|
21
|
-
data[:_aliases] = @aliases if @aliases
|
|
22
|
-
|
|
23
|
-
# Gli hook di classe vengono solo letti (mai azzerati): devono valere
|
|
24
|
-
# per ogni chiamata, anche concorrente
|
|
25
|
-
data[:_before_actions] = @before_actions.dup if @before_actions
|
|
26
|
-
data[:_after_actions] = @after_actions.dup if @after_actions
|
|
27
|
-
|
|
28
|
-
WithReducerFactory.make(self).with(data)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def reduce(*actions)
|
|
32
|
-
with({}).reduce(actions)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def reduce_if(condition_block, steps)
|
|
36
|
-
ReduceIf.run(self, condition_block, steps)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def reduce_until(condition_block, steps)
|
|
40
|
-
ReduceUntil.run(self, condition_block, steps)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def iterate(collection_key, steps)
|
|
44
|
-
Iterate.run(self, collection_key, steps)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def execute(code_block)
|
|
48
|
-
Execute.run(code_block)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def with_callback(action, steps)
|
|
52
|
-
WithCallback.run(self, action, steps)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def log_with(logger)
|
|
56
|
-
@logger = logger
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def logger
|
|
60
|
-
@logger
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def add_to_context(**args)
|
|
64
|
-
args.map do |key, value|
|
|
65
|
-
execute(->(ctx) { ctx[key.to_sym] = value })
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def add_aliases(args)
|
|
70
|
-
execute(->(ctx) { ctx.assign_aliases(ctx.aliases.merge(args)) })
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
module Macros
|
|
75
|
-
def aliases(key_hash)
|
|
76
|
-
@aliases = key_hash
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# This looks like an accessor,
|
|
80
|
-
# but it's used as a macro in the Organizer
|
|
81
|
-
def before_actions(*logic)
|
|
82
|
-
self.before_actions = logic
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def before_actions=(logic)
|
|
86
|
-
@before_actions = logic.nil? ? nil : [logic].flatten
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def append_before_actions(action)
|
|
90
|
-
@before_actions ||= []
|
|
91
|
-
@before_actions.push(action)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def remove_before_actions(action)
|
|
95
|
-
@before_actions&.delete(action)
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# This looks like an accessor,
|
|
99
|
-
# but it's used as a macro in the Organizer
|
|
100
|
-
def after_actions(*logic)
|
|
101
|
-
self.after_actions = logic
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
def after_actions=(logic)
|
|
105
|
-
@after_actions = logic.nil? ? nil : [logic].flatten
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
def append_after_actions(action)
|
|
109
|
-
@after_actions ||= []
|
|
110
|
-
@after_actions.push(action)
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module FunctionalLightService
|
|
4
|
-
module Testing
|
|
5
|
-
class ContextFactory
|
|
6
|
-
attr_reader :organizer
|
|
7
|
-
|
|
8
|
-
def self.make_from(organizer)
|
|
9
|
-
new(organizer)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def for(action)
|
|
13
|
-
@target_action = action
|
|
14
|
-
self
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# More than one arguments can be passed to the
|
|
18
|
-
# Organizer's #call method
|
|
19
|
-
def with(...)
|
|
20
|
-
hook = nil
|
|
21
|
-
hook = ->(ctx) do
|
|
22
|
-
if ctx.current_action == @target_action
|
|
23
|
-
# L'hook non deve essere re-invocato quando il context
|
|
24
|
-
# verra' usato con Action#execute nel test
|
|
25
|
-
ctx[:_before_actions].delete(hook)
|
|
26
|
-
|
|
27
|
-
throw(:return_ctx_from_execution, ctx)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
@organizer.append_before_actions(hook)
|
|
32
|
-
|
|
33
|
-
begin
|
|
34
|
-
catch(:return_ctx_from_execution) do
|
|
35
|
-
@organizer.call(...)
|
|
36
|
-
end
|
|
37
|
-
ensure
|
|
38
|
-
# L'hook e' per-chiamata: la classe organizer non deve conservarlo
|
|
39
|
-
@organizer.remove_before_actions(hook)
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def initialize(organizer)
|
|
44
|
-
@organizer = organizer
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
data/resources/fail_actions.png
DELETED
|
Binary file
|
data/resources/light-service.png
DELETED
|
Binary file
|
|
Binary file
|
data/resources/skip_actions.png
DELETED
|
Binary file
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'test_doubles'
|
|
3
|
-
|
|
4
|
-
RSpec.describe TestDoubles::AdditionOrganizer do
|
|
5
|
-
it 'Adds 1, 2 and 3 to the initial value of 1' do
|
|
6
|
-
result = TestDoubles::AdditionOrganizer.call(1)
|
|
7
|
-
number = result.fetch(:number)
|
|
8
|
-
|
|
9
|
-
expect(number).to eq(7)
|
|
10
|
-
end
|
|
11
|
-
end
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'test_doubles'
|
|
3
|
-
|
|
4
|
-
RSpec.describe 'Action after_actions' do
|
|
5
|
-
# Gli hook restano sulla classe (non vengono piu consumati da #with):
|
|
6
|
-
# i test double sono condivisi, quindi vanno ripuliti dopo ogni esempio
|
|
7
|
-
after do
|
|
8
|
-
TestDoubles::AdditionOrganizer.after_actions = nil
|
|
9
|
-
TestDoubles::TestIterate.after_actions = nil
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
describe 'works with simple organizers - from outside' do
|
|
13
|
-
it 'can be used to inject code block before each action' do
|
|
14
|
-
TestDoubles::AdditionOrganizer.after_actions = ->(ctx) do
|
|
15
|
-
ctx.number -= 2 if ctx.current_action == TestDoubles::AddsThreeAction
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
result = TestDoubles::AdditionOrganizer.call(0)
|
|
19
|
-
|
|
20
|
-
expect(result.fetch(:number)).to eq(4)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
it 'works with iterator' do
|
|
24
|
-
TestDoubles::TestIterate.after_actions = [
|
|
25
|
-
->(ctx) { ctx.number -= 2 if ctx.current_action == TestDoubles::AddsOneAction }
|
|
26
|
-
]
|
|
27
|
-
|
|
28
|
-
result = TestDoubles::TestIterate.call(:number => 0,
|
|
29
|
-
:counters => [1, 2, 3, 4])
|
|
30
|
-
|
|
31
|
-
expect(result).to be_success
|
|
32
|
-
expect(result.number).to eq(-4)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
describe 'can be added to organizers declaratively' do
|
|
37
|
-
module AfterActions
|
|
38
|
-
class AdditionOrganizer
|
|
39
|
-
extend FunctionalLightService::Organizer
|
|
40
|
-
|
|
41
|
-
after_actions ->(ctx) do
|
|
42
|
-
ctx.number -= 2 if ctx.current_action == TestDoubles::AddsOneAction
|
|
43
|
-
end,
|
|
44
|
-
->(ctx) do
|
|
45
|
-
ctx.number -= 3 if ctx.current_action == TestDoubles::AddsThreeAction
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def self.call(number)
|
|
49
|
-
with(:number => number).reduce(actions)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def self.actions
|
|
53
|
-
[
|
|
54
|
-
TestDoubles::AddsOneAction,
|
|
55
|
-
TestDoubles::AddsTwoAction,
|
|
56
|
-
TestDoubles::AddsThreeAction
|
|
57
|
-
]
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it 'accepts after_actions hook lambdas from organizer' do
|
|
63
|
-
result = AfterActions::AdditionOrganizer.call(0)
|
|
64
|
-
|
|
65
|
-
expect(result.fetch(:number)).to eq(1)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
it 'keeps the declarative hooks on every subsequent call' do
|
|
69
|
-
first = AfterActions::AdditionOrganizer.call(0)
|
|
70
|
-
second = AfterActions::AdditionOrganizer.call(0)
|
|
71
|
-
|
|
72
|
-
expect(first.fetch(:number)).to eq(1)
|
|
73
|
-
expect(second.fetch(:number)).to eq(1)
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
describe 'after_actions can be appended' do
|
|
78
|
-
it 'adds to the :_after_actions collection' do
|
|
79
|
-
TestDoubles::AdditionOrganizer.append_after_actions(
|
|
80
|
-
->(ctx) { ctx.number -= 3 if ctx.current_action == TestDoubles::AddsThreeAction }
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
result = TestDoubles::AdditionOrganizer.call(0)
|
|
84
|
-
expect(result.fetch(:number)).to eq(3)
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'test_doubles'
|
|
3
|
-
|
|
4
|
-
describe 'Executing arbitrary code around each action' do
|
|
5
|
-
it 'can be used to log data' do
|
|
6
|
-
context = { :number => 0, :logger => TestDoubles::TestLogger.new }
|
|
7
|
-
|
|
8
|
-
result = TestDoubles::AroundEachOrganizer.call(context)
|
|
9
|
-
|
|
10
|
-
expect(result.fetch(:number)).to eq(2)
|
|
11
|
-
expect(result[:logger].logs).to eq(
|
|
12
|
-
[{
|
|
13
|
-
:action => TestDoubles::AddsTwoActionWithFetch,
|
|
14
|
-
:before => 0,
|
|
15
|
-
:after => 2
|
|
16
|
-
}]
|
|
17
|
-
)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'test_doubles'
|
|
3
|
-
|
|
4
|
-
RSpec.describe 'Action before_actions' do
|
|
5
|
-
# Gli hook restano sulla classe (non vengono piu consumati da #with):
|
|
6
|
-
# i test double sono condivisi, quindi vanno ripuliti dopo ogni esempio
|
|
7
|
-
after do
|
|
8
|
-
TestDoubles::AdditionOrganizer.before_actions = nil
|
|
9
|
-
TestDoubles::TestIterate.before_actions = nil
|
|
10
|
-
TestDoubles::TestWithCallback.before_actions = nil
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
describe 'works with simple organizers - from outside' do
|
|
14
|
-
it 'can be used to inject code block before each action' do
|
|
15
|
-
TestDoubles::AdditionOrganizer.before_actions = ->(ctx) do
|
|
16
|
-
ctx.number -= 2 if ctx.current_action == TestDoubles::AddsThreeAction
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
result = TestDoubles::AdditionOrganizer.call(0)
|
|
20
|
-
|
|
21
|
-
expect(result.fetch(:number)).to eq(4)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
it 'works with iterator' do
|
|
25
|
-
TestDoubles::TestIterate.before_actions = [
|
|
26
|
-
->(ctx) { ctx.number -= 2 if ctx.current_action == TestDoubles::AddsOneAction }
|
|
27
|
-
]
|
|
28
|
-
|
|
29
|
-
result = TestDoubles::TestIterate.call(:number => 0,
|
|
30
|
-
:counters => [1, 2, 3, 4])
|
|
31
|
-
|
|
32
|
-
expect(result).to be_success
|
|
33
|
-
expect(result.number).to eq(-4)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
describe 'can be added to organizers declaratively' do
|
|
38
|
-
module BeforeActions
|
|
39
|
-
class AdditionOrganizer
|
|
40
|
-
extend FunctionalLightService::Organizer
|
|
41
|
-
|
|
42
|
-
before_actions ->(ctx) do
|
|
43
|
-
ctx.number -= 2 if ctx.current_action == TestDoubles::AddsOneAction
|
|
44
|
-
end,
|
|
45
|
-
->(ctx) do
|
|
46
|
-
ctx.number -= 3 if ctx.current_action == TestDoubles::AddsThreeAction
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def self.call(number)
|
|
50
|
-
with(:number => number).reduce(actions)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def self.actions
|
|
54
|
-
[
|
|
55
|
-
TestDoubles::AddsOneAction,
|
|
56
|
-
TestDoubles::AddsTwoAction,
|
|
57
|
-
TestDoubles::AddsThreeAction
|
|
58
|
-
]
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
it 'accepts before_actions hook lambdas from organizer' do
|
|
64
|
-
result = BeforeActions::AdditionOrganizer.call(0)
|
|
65
|
-
|
|
66
|
-
expect(result.fetch(:number)).to eq(1)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
it 'keeps the declarative hooks on every subsequent call' do
|
|
70
|
-
first = BeforeActions::AdditionOrganizer.call(0)
|
|
71
|
-
second = BeforeActions::AdditionOrganizer.call(0)
|
|
72
|
-
|
|
73
|
-
expect(first.fetch(:number)).to eq(1)
|
|
74
|
-
expect(second.fetch(:number)).to eq(1)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
describe 'works with callbacks' do
|
|
79
|
-
it 'can interact with actions from the outside' do
|
|
80
|
-
TestDoubles::TestWithCallback.before_actions = [
|
|
81
|
-
->(ctx) { ctx.total -= 1000 if ctx.current_action == TestDoubles::AddToTotalAction }
|
|
82
|
-
]
|
|
83
|
-
result = TestDoubles::TestWithCallback.call
|
|
84
|
-
|
|
85
|
-
expect(result.counter).to eq(3)
|
|
86
|
-
expect(result.total).to eq(-2994)
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
describe 'can halt all execution with a raised error' do
|
|
91
|
-
it 'does not call the rest of the callback steps' do
|
|
92
|
-
class SkipContextError < StandardError
|
|
93
|
-
attr_reader :ctx
|
|
94
|
-
|
|
95
|
-
def initialize(msg, ctx)
|
|
96
|
-
@ctx = ctx
|
|
97
|
-
super(msg)
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
TestDoubles::TestWithCallback.before_actions = [
|
|
101
|
-
->(ctx) do
|
|
102
|
-
if ctx.current_action == TestDoubles::IncrementCountAction
|
|
103
|
-
ctx.total -= 1000
|
|
104
|
-
raise SkipContextError.new("stop context now", ctx)
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
]
|
|
108
|
-
begin
|
|
109
|
-
TestDoubles::TestWithCallback.call
|
|
110
|
-
rescue SkipContextError => e
|
|
111
|
-
expect(e.ctx).not_to be_empty
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe "Log from an organizer with a custom logger" do
|
|
4
|
-
context "when overriding the global FunctionalLightService organizer" do
|
|
5
|
-
let(:global_logger_organizer) do
|
|
6
|
-
Class.new do
|
|
7
|
-
extend FunctionalLightService::Organizer
|
|
8
|
-
|
|
9
|
-
def self.call(number)
|
|
10
|
-
with(:number => number).reduce(actions)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def self.actions
|
|
14
|
-
[
|
|
15
|
-
TestDoubles::AddsOneAction,
|
|
16
|
-
TestDoubles::AddsTwoAction,
|
|
17
|
-
TestDoubles::AddsThreeAction
|
|
18
|
-
]
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
let(:global_logger_string) { StringIO.new }
|
|
24
|
-
|
|
25
|
-
let(:custom_logger_string) { StringIO.new }
|
|
26
|
-
let(:custom_logger_organizer) do
|
|
27
|
-
custom_logger = Logger.new(custom_logger_string)
|
|
28
|
-
|
|
29
|
-
Class.new do
|
|
30
|
-
extend FunctionalLightService::Organizer
|
|
31
|
-
|
|
32
|
-
log_with custom_logger
|
|
33
|
-
|
|
34
|
-
def self.call(coffee, this_hot = :very_hot)
|
|
35
|
-
with(:milk => this_hot, :coffee => coffee)
|
|
36
|
-
.reduce(TestDoubles::MakesLatteAction,
|
|
37
|
-
TestDoubles::AddsTwoActionWithFetch)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
before do
|
|
43
|
-
@original_global_logger = FunctionalLightService::Configuration.logger
|
|
44
|
-
FunctionalLightService::Configuration.logger = Logger.new(global_logger_string)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
it "logs in own logger" do
|
|
48
|
-
global_logger_organizer.call(1)
|
|
49
|
-
custom_logger_organizer.call(:coffee => "Cappucino")
|
|
50
|
-
|
|
51
|
-
expect(custom_logger_string.string).to include("MakesLatteAction")
|
|
52
|
-
expect(custom_logger_string.string).to_not include("AddsOneAction")
|
|
53
|
-
expect(global_logger_string.string).to include("AddsOneAction")
|
|
54
|
-
expect(global_logger_string.string).to_not include("MakesLatteAction")
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
after do
|
|
58
|
-
FunctionalLightService::Configuration.logger = @original_global_logger
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
# Maybe()/Null e il monkey-patch di Object sono opt-in: non fanno parte
|
|
3
|
-
# del require chain di default della gem
|
|
4
|
-
require 'functional-light-service/functional/maybe'
|
|
5
|
-
|
|
6
|
-
describe "deprecation warnings" do
|
|
7
|
-
around do |example|
|
|
8
|
-
FunctionalLightService::Deprecations.silenced = false
|
|
9
|
-
FunctionalLightService::Deprecations.reset!
|
|
10
|
-
example.run
|
|
11
|
-
ensure
|
|
12
|
-
FunctionalLightService::Deprecations.silenced = true
|
|
13
|
-
FunctionalLightService::Deprecations.reset!
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
context "when including FunctionalLightService::Organizer" do
|
|
17
|
-
it "warns on stderr" do
|
|
18
|
-
expect do
|
|
19
|
-
class OrganizerIncludingLS
|
|
20
|
-
include FunctionalLightService::Organizer
|
|
21
|
-
end
|
|
22
|
-
end.to output(/Including FunctionalLightService::Organizer is deprecated/).to_stderr
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
context "when including FunctionalLightService::Action" do
|
|
27
|
-
it "warns on stderr" do
|
|
28
|
-
expect do
|
|
29
|
-
class ActionIncludingLS
|
|
30
|
-
include FunctionalLightService::Action
|
|
31
|
-
end
|
|
32
|
-
end.to output(/Including FunctionalLightService::Action is deprecated/).to_stderr
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
context "when using Maybe/Null" do
|
|
37
|
-
it "warns once per process" do
|
|
38
|
-
expect { Maybe(nil) }
|
|
39
|
-
.to output(%r{Maybe\(\)/Null are deprecated}).to_stderr
|
|
40
|
-
# warn-once: la seconda invocazione non emette nulla
|
|
41
|
-
expect { Maybe(nil) }.not_to output.to_stderr
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
context "when using the exotic operators" do
|
|
46
|
-
include FunctionalLightService::Prelude::Result
|
|
47
|
-
|
|
48
|
-
it "Result#>= warns and delegates to #try" do
|
|
49
|
-
result = nil
|
|
50
|
-
expect { result = Success(1) >= ->(v) { Success(v + 1) } }
|
|
51
|
-
.to output(/Result#>= is deprecated/).to_stderr
|
|
52
|
-
expect(result).to eq(Success(2))
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
it "Result#<< warns and delegates to #pipe" do
|
|
56
|
-
expect { Success(1) << ->(_v) {} }
|
|
57
|
-
.to output(/Result#<< is deprecated/).to_stderr
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
it "Result#+ warns and still combines" do
|
|
61
|
-
result = nil
|
|
62
|
-
expect { result = Success(1) + Success(2) }
|
|
63
|
-
.to output(/Result#\+ is deprecated/).to_stderr
|
|
64
|
-
expect(result).to eq(Success(3))
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
it "Option#+ warns and still combines" do
|
|
68
|
-
some = FunctionalLightService::Option::Some
|
|
69
|
-
result = nil
|
|
70
|
-
expect { result = some.new(1) + some.new(2) }
|
|
71
|
-
.to output(/Option#\+ is deprecated/).to_stderr
|
|
72
|
-
expect(result).to eq(some.new(3))
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
context "when silenced" do
|
|
77
|
-
it "emits nothing" do
|
|
78
|
-
FunctionalLightService::Deprecations.silenced = true
|
|
79
|
-
expect { Maybe(nil) }.not_to output.to_stderr
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|