functional-light-service 6.2.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 -36
- metadata +14 -307
- data/.github/workflows/project-build.yml +0 -71
- data/.gitignore +0 -24
- 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 -292
- data/CODE_OF_CONDUCT.md +0 -22
- data/Gemfile +0 -4
- data/LICENSE +0 -22
- data/README.md +0 -1663
- 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 -35
- 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 -145
- data/lib/functional-light-service/configuration.rb +0 -36
- data/lib/functional-light-service/context/key_verifier.rb +0 -124
- data/lib/functional-light-service/context.rb +0 -208
- data/lib/functional-light-service/deprecations.rb +0 -26
- data/lib/functional-light-service/errors.rb +0 -9
- 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/i18n/localization_adapter.rb +0 -50
- data/lib/functional-light-service/localization_adapter.rb +0 -39
- data/lib/functional-light-service/localization_map.rb +0 -9
- 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_case.rb +0 -50
- data/lib/functional-light-service/organizer/reduce_if.rb +0 -19
- data/lib/functional-light-service/organizer/reduce_if_else.rb +0 -23
- data/lib/functional-light-service/organizer/reduce_until.rb +0 -22
- data/lib/functional-light-service/organizer/reduce_while.rb +0 -31
- 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 -111
- data/lib/functional-light-service/organizer.rb +0 -129
- 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 -54
- data/spec/acceptance/organizer/around_each_with_reduce_if_spec.rb +0 -42
- data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +0 -90
- data/spec/acceptance/organizer/execute_spec.rb +0 -67
- data/spec/acceptance/organizer/iterate_spec.rb +0 -44
- data/spec/acceptance/organizer/reduce_case_spec.rb +0 -65
- data/spec/acceptance/organizer/reduce_if_else_spec.rb +0 -60
- data/spec/acceptance/organizer/reduce_if_spec.rb +0 -89
- data/spec/acceptance/organizer/reduce_until_spec.rb +0 -49
- data/spec/acceptance/organizer/reduce_while_spec.rb +0 -96
- 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/skip_all_remaining_spec.rb +0 -139
- 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_optional_expected_keys_spec.rb +0 -107
- data/spec/action_promised_keys_spec.rb +0 -126
- data/spec/action_spec.rb +0 -97
- data/spec/context/inspect_spec.rb +0 -52
- data/spec/context_spec.rb +0 -301
- 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/i18n_localization_adapter_spec.rb +0 -83
- 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 -66
- 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 -32
- data/spec/support.rb +0 -1
- data/spec/test_doubles.rb +0 -656
- 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
data/spec/lib/enum_spec.rb
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe FunctionalLightService::Enum do
|
|
4
|
-
include FunctionalLightService
|
|
5
|
-
|
|
6
|
-
it "can't use value" do
|
|
7
|
-
expect do
|
|
8
|
-
InvalidEnum = FunctionalLightService.enum do
|
|
9
|
-
Unary(:value)
|
|
10
|
-
end
|
|
11
|
-
end.to raise_error ArgumentError
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
context "Nullary, Unary, Binary" do
|
|
15
|
-
MyEnym = FunctionalLightService.enum do
|
|
16
|
-
Nullary()
|
|
17
|
-
Unary(:a)
|
|
18
|
-
Binary(:a, :b)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
it "can't instantiate parent" do
|
|
22
|
-
expect { MyEnym.new }.to \
|
|
23
|
-
raise_error NoMethodError, /private method [`']new'/
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it "Nullary" do
|
|
27
|
-
n = MyEnym.Nullary
|
|
28
|
-
|
|
29
|
-
expect(n).to be_a MyEnym
|
|
30
|
-
expect(n).to be_a MyEnym::Nullary
|
|
31
|
-
expect(n.name).to eq "Nullary"
|
|
32
|
-
expect { n.value }.to raise_error NoMethodError
|
|
33
|
-
expect(n.inspect).to eq "Nullary"
|
|
34
|
-
expect(n.to_s).to eq ""
|
|
35
|
-
# rubocop:disable Lint/EmptyBlock
|
|
36
|
-
expect(n.fmap {}).to eq n
|
|
37
|
-
# rubocop:enable Lint/EmptyBlock
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it "Unary" do
|
|
41
|
-
u = MyEnym::Unary(1)
|
|
42
|
-
|
|
43
|
-
expect(u).to be_a MyEnym
|
|
44
|
-
expect(u).to be_a MyEnym::Unary
|
|
45
|
-
expect(u.name).to eq "Unary"
|
|
46
|
-
expect(u.a).to eq 1
|
|
47
|
-
expect(u.value).to eq 1
|
|
48
|
-
expect(u.inspect).to eq "Unary(1)"
|
|
49
|
-
expect(u.to_s).to eq "1"
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "Binary" do
|
|
53
|
-
# hash
|
|
54
|
-
b = MyEnym::Binary(:a => 1, :b => 2)
|
|
55
|
-
expect(b).to be_a MyEnym
|
|
56
|
-
expect(b).to be_a MyEnym::Binary
|
|
57
|
-
expect(b.name).to eq "Binary"
|
|
58
|
-
expect(b.inspect).to eq "Binary(a: 1, b: 2)"
|
|
59
|
-
|
|
60
|
-
expect(b.a).to eq 1
|
|
61
|
-
expect(b.b).to eq 2
|
|
62
|
-
expect(b.value).to eq(:a => 1, :b => 2)
|
|
63
|
-
|
|
64
|
-
# values only
|
|
65
|
-
b = MyEnym::Binary(1, 2)
|
|
66
|
-
expect(b.value).to eq(:a => 1, :b => 2)
|
|
67
|
-
|
|
68
|
-
# other names are ok
|
|
69
|
-
b = MyEnym::Binary(:c => 1, :d => 2)
|
|
70
|
-
expect(b.value).to eq(:a => 1, :b => 2)
|
|
71
|
-
|
|
72
|
-
expect { MyEnym::Binary(1) }.to raise_error ArgumentError
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
it "generated enum" do
|
|
76
|
-
expect(MyEnym.variants.sort).to eq %i[Unary Binary Nullary].sort
|
|
77
|
-
expect(MyEnym.constants.sort.inspect).to eq %i[Matcher Unary Binary Nullary].sort.to_s
|
|
78
|
-
|
|
79
|
-
b = MyEnym::Binary(:a => 1, :b => 2)
|
|
80
|
-
|
|
81
|
-
res =
|
|
82
|
-
MyEnym.match(b) do
|
|
83
|
-
Nullary() { 0 }
|
|
84
|
-
Unary() { |a| a }
|
|
85
|
-
Binary() { |x, y| [x, y] }
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
expect(res).to eq [1, 2]
|
|
89
|
-
|
|
90
|
-
res =
|
|
91
|
-
b.match do
|
|
92
|
-
Nullary() { 0 }
|
|
93
|
-
Unary() { |a| a }
|
|
94
|
-
Binary() { |x, y| [x, y] }
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
expect(res).to eq [1, 2]
|
|
98
|
-
|
|
99
|
-
expect do
|
|
100
|
-
b.match do
|
|
101
|
-
Nullary # Nullary is treated as a constant
|
|
102
|
-
end
|
|
103
|
-
end.to raise_error(NameError)
|
|
104
|
-
|
|
105
|
-
expect do
|
|
106
|
-
b.match do
|
|
107
|
-
Nullary()
|
|
108
|
-
Unary()
|
|
109
|
-
Binary()
|
|
110
|
-
end
|
|
111
|
-
end.to raise_error ArgumentError, "No block given to `Nullary`"
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
end
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe "native Ruby pattern matching (case/in) support" do
|
|
4
|
-
include FunctionalLightService::Prelude::Result
|
|
5
|
-
include FunctionalLightService::Prelude::Option
|
|
6
|
-
|
|
7
|
-
Result = FunctionalLightService::Result
|
|
8
|
-
Option = FunctionalLightService::Option
|
|
9
|
-
|
|
10
|
-
it "deconstructs Success/Failure positionally" do
|
|
11
|
-
matched =
|
|
12
|
-
case Success(42)
|
|
13
|
-
in Result::Success[value] then "success: #{value}"
|
|
14
|
-
in Result::Failure[error] then "failure: #{error}"
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
expect(matched).to eq("success: 42")
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it "deconstructs Failure positionally" do
|
|
21
|
-
matched =
|
|
22
|
-
case Failure(:boom)
|
|
23
|
-
in Result::Success[value] then "success: #{value}"
|
|
24
|
-
in Result::Failure[error] then "failure: #{error}"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
expect(matched).to eq("failure: boom")
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it "deconstructs by keys using the variant's field names" do
|
|
31
|
-
matched =
|
|
32
|
-
case Success(42)
|
|
33
|
-
in Result::Success(s:) then s
|
|
34
|
-
in Result::Failure(f:) then f
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
expect(matched).to eq(42)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it "deconstructs Some and None" do
|
|
41
|
-
some_result =
|
|
42
|
-
case Some(7)
|
|
43
|
-
in Option::Some[v] then v
|
|
44
|
-
in Option::None then :none
|
|
45
|
-
end
|
|
46
|
-
none_result =
|
|
47
|
-
case None()
|
|
48
|
-
in Option::Some[v] then v
|
|
49
|
-
in Option::None then :none
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
expect(some_result).to eq(7)
|
|
53
|
-
expect(none_result).to eq(:none)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
Shape = FunctionalLightService.enum do
|
|
57
|
-
Point(:x, :y)
|
|
58
|
-
Origin()
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
it "deconstructs multi-field (Binary) variants by keys" do
|
|
62
|
-
matched =
|
|
63
|
-
case Shape::Point.new(1, 2)
|
|
64
|
-
in Shape::Point(x:, y:) then [x, y]
|
|
65
|
-
in Shape::Origin then [0, 0]
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
expect(matched).to eq([1, 2])
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def None # rubocop:disable Naming/MethodName
|
|
72
|
-
FunctionalLightService::Option::None.new
|
|
73
|
-
end
|
|
74
|
-
end
|
|
@@ -1,66 +0,0 @@
|
|
|
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
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'test_doubles'
|
|
3
|
-
|
|
4
|
-
describe FunctionalLightService::Organizer::WithReducer do
|
|
5
|
-
let(:context) { FunctionalLightService::Context.make }
|
|
6
|
-
let(:action1) { TestDoubles::NullAction }
|
|
7
|
-
let(:action2) { TestDoubles::NullAction.clone }
|
|
8
|
-
let(:actions) { [action1, action2] }
|
|
9
|
-
|
|
10
|
-
before { context.current_action = action2 }
|
|
11
|
-
|
|
12
|
-
it "reduces the provided actions" do
|
|
13
|
-
result = described_class.new.with(context).reduce(actions)
|
|
14
|
-
|
|
15
|
-
expect(result).to eq(context)
|
|
16
|
-
expect(result).to be_success
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
it "executes a handler around each action and continues reducing" do
|
|
20
|
-
expect(action1).to receive(:execute).with(context).and_return(context)
|
|
21
|
-
|
|
22
|
-
result = described_class.new.with(context)
|
|
23
|
-
.around_each(TestDoubles::AroundEachNullHandler)
|
|
24
|
-
.reduce([action1])
|
|
25
|
-
|
|
26
|
-
expect(result).to eq(context)
|
|
27
|
-
expect(result).to be_success
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
context "when FailWithRollbackError is caught" do
|
|
31
|
-
it "reduces the rollback" do
|
|
32
|
-
expect(action1).to receive(:execute).with(context).and_return(context)
|
|
33
|
-
expect(action2).to receive(:execute).with(context) do
|
|
34
|
-
raise FunctionalLightService::FailWithRollbackError
|
|
35
|
-
end
|
|
36
|
-
expect(action1).to receive(:rollback).with(context).and_return(context)
|
|
37
|
-
expect(action2).to receive(:rollback).with(context).and_return(context)
|
|
38
|
-
|
|
39
|
-
result = described_class.new.with(context).reduce(actions)
|
|
40
|
-
|
|
41
|
-
expect(result).to eq(context)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
it "reduces the rollback with an action without `rollback`" do
|
|
45
|
-
expect(action1).to receive(:execute).with(context).and_return(context)
|
|
46
|
-
expect(action2).to receive(:execute).with(context) do
|
|
47
|
-
raise FunctionalLightService::FailWithRollbackError
|
|
48
|
-
end
|
|
49
|
-
expect(action2).to receive(:rollback).with(context).and_return(context)
|
|
50
|
-
|
|
51
|
-
result = described_class.new.with(context).reduce(actions)
|
|
52
|
-
|
|
53
|
-
expect(result).to eq(context)
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'test_doubles'
|
|
3
|
-
|
|
4
|
-
describe "organizer aliases macro" do
|
|
5
|
-
let(:organizer_with_alias) do
|
|
6
|
-
Class.new do
|
|
7
|
-
extend FunctionalLightService::Organizer
|
|
8
|
-
|
|
9
|
-
aliases :promised_key => :expected_key
|
|
10
|
-
|
|
11
|
-
def self.call(ctx = {})
|
|
12
|
-
with(ctx).reduce(
|
|
13
|
-
[
|
|
14
|
-
TestDoubles::PromisesPromisedKeyAction,
|
|
15
|
-
TestDoubles::ExpectsExpectedKeyAction
|
|
16
|
-
]
|
|
17
|
-
)
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
context "when aliases is invoked" do
|
|
23
|
-
it "makes aliases available to the actions" do
|
|
24
|
-
result = organizer_with_alias.call
|
|
25
|
-
expect(result[:expected_key]).to eq(result[:promised_key])
|
|
26
|
-
expect(result.expected_key).to eq(result[:promised_key])
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
data/spec/organizer_spec.rb
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require 'test_doubles'
|
|
3
|
-
|
|
4
|
-
describe FunctionalLightService::Organizer do
|
|
5
|
-
let(:ctx) { FunctionalLightService::Context.make(:user => user) }
|
|
6
|
-
let(:user) { double(:user) }
|
|
7
|
-
|
|
8
|
-
context "when #with is called with hash" do
|
|
9
|
-
before do
|
|
10
|
-
expect(TestDoubles::AnAction).to receive(:execute)
|
|
11
|
-
.with(ctx)
|
|
12
|
-
.and_return(ctx)
|
|
13
|
-
expect(TestDoubles::AnotherAction).to receive(:execute)
|
|
14
|
-
.with(ctx)
|
|
15
|
-
.and_return(ctx)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
it "implicitly creates a Context" do
|
|
19
|
-
result = TestDoubles::AnOrganizer.call(:user => user)
|
|
20
|
-
expect(result).to eq(ctx)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
it "sets itself as the organizer" do
|
|
24
|
-
result = TestDoubles::AnOrganizer.call(:user => user)
|
|
25
|
-
expect(result.organized_by).to eq TestDoubles::AnOrganizer
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
context "when #with is called with Context" do
|
|
30
|
-
before do
|
|
31
|
-
expect(TestDoubles::AnAction).to receive(:execute)
|
|
32
|
-
.with(ctx)
|
|
33
|
-
.and_return(ctx)
|
|
34
|
-
expect(TestDoubles::AnotherAction).to receive(:execute)
|
|
35
|
-
.with(ctx)
|
|
36
|
-
.and_return(ctx)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it "uses that Context without recreating it" do
|
|
40
|
-
result = TestDoubles::AnOrganizer.call(ctx)
|
|
41
|
-
expect(result).to eq(ctx)
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
context "when no Actions are specified" do
|
|
46
|
-
it "throws a Runtime error" do
|
|
47
|
-
expect { TestDoubles::AnOrganizer.do_something_with_no_actions(ctx) }.to \
|
|
48
|
-
raise_error(RuntimeError, "No action(s) were provided")
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
context "when aliases are declared" do
|
|
53
|
-
let(:organizer) do
|
|
54
|
-
Class.new do
|
|
55
|
-
extend FunctionalLightService::Organizer
|
|
56
|
-
|
|
57
|
-
aliases :foo => :bar
|
|
58
|
-
|
|
59
|
-
def self.call
|
|
60
|
-
with.reduce(TestDoubles::AnAction)
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
it "merges the aliases into the data" do
|
|
66
|
-
with_reducer = double(:reduce => true)
|
|
67
|
-
|
|
68
|
-
allow(described_class::WithReducerFactory).to receive(:make)
|
|
69
|
-
.and_return(with_reducer)
|
|
70
|
-
|
|
71
|
-
expect(with_reducer).to receive(:with)
|
|
72
|
-
.with(hash_including(:_aliases => { :foo => :bar }))
|
|
73
|
-
.and_return(with_reducer)
|
|
74
|
-
|
|
75
|
-
organizer.call
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
context "when an organizer is nested and reduced within another" do
|
|
80
|
-
let(:reduced) { TestDoubles::NestingOrganizer.call(ctx) }
|
|
81
|
-
let(:organizer_result) do
|
|
82
|
-
TestDoubles::NotExplicitlyReturningContextOrganizer.call(ctx)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it "reduces an organizer which returns something" do
|
|
86
|
-
expect(organizer_result).to eq([1, 2, 3])
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
it "adds :foo and :bar to the context" do
|
|
90
|
-
reduced
|
|
91
|
-
expect(ctx[:foo]).to eq([1, 2, 3])
|
|
92
|
-
expect(ctx[:bar]).to eq(ctx[:foo])
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
it "returns the context" do
|
|
96
|
-
expect(reduced).to eq(ctx)
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
context "can add items to the context" do
|
|
101
|
-
specify 'with #add_to_context' do
|
|
102
|
-
result = TestDoubles::AnOrganizerThatAddsToContext.call
|
|
103
|
-
expect(result[:strongest_avenger]).to eq :thor
|
|
104
|
-
expect(result[:last_jedi]).to eq "Rey"
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
context "can assign key aliaeses" do
|
|
109
|
-
it 'with #add_aliases' do
|
|
110
|
-
result = TestDoubles::AnOrganizerThatAddsAliases.call
|
|
111
|
-
expect(result[:foo]).to eq :bar
|
|
112
|
-
expect(result[:baz]).to eq :bar
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
data/spec/readme_spec.rb
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
include FunctionalLightService::Prelude::Result
|
|
4
|
-
|
|
5
|
-
Success(1).to_s # => "1"
|
|
6
|
-
Success(Success(1)) # => Success(1)
|
|
7
|
-
|
|
8
|
-
Failure(1).to_s # => "1"
|
|
9
|
-
Failure(Failure(1)) # => Failure(1)
|
|
10
|
-
|
|
11
|
-
Success(1).fmap { |v| v + 1 } # => Success(2)
|
|
12
|
-
Failure(1).fmap { |v| v - 1 } # => Failure(0)
|
|
13
|
-
|
|
14
|
-
Threenum = FunctionalLightService.enum do
|
|
15
|
-
Nullary()
|
|
16
|
-
Unary(:a)
|
|
17
|
-
Binary(:a, :b)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
FunctionalLightService.impl(Threenum) do
|
|
21
|
-
def sum
|
|
22
|
-
match do
|
|
23
|
-
Nullary() { 0 }
|
|
24
|
-
Unary() { |u| u }
|
|
25
|
-
Binary() { |a, b| a + b }
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def +(other)
|
|
30
|
-
match do
|
|
31
|
-
Nullary() { other.sum }
|
|
32
|
-
Unary() { |_a| sum + other.sum }
|
|
33
|
-
Binary() { |_a, _b| sum + other.sum }
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
describe Threenum do
|
|
39
|
-
it "works" do
|
|
40
|
-
expect(Threenum.Nullary + Threenum.Unary(1)).to eq 1
|
|
41
|
-
expect(Threenum.Nullary + Threenum.Binary(2, 3)).to eq 5
|
|
42
|
-
expect(Threenum.Unary(1) + Threenum.Binary(2, 3)).to eq 6
|
|
43
|
-
expect(Threenum.Binary(2, 3) + Threenum.Binary(2, 3)).to eq 10
|
|
44
|
-
end
|
|
45
|
-
end
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require_relative 'tax/calculates_order_tax_action'
|
|
3
|
-
|
|
4
|
-
describe CalculatesOrderTaxAction do
|
|
5
|
-
let(:order) { double('order') }
|
|
6
|
-
let(:context) do
|
|
7
|
-
data = { :order => order, :tax_percentage => 7.2 }
|
|
8
|
-
FunctionalLightService::Context.make(data)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
it "calculates the tax based on the tax percentage" do
|
|
12
|
-
allow(order).to receive_messages(:total => 100)
|
|
13
|
-
expect(order).to receive(:tax=).with 7.2
|
|
14
|
-
CalculatesOrderTaxAction.execute(context)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require_relative 'tax/calculates_tax'
|
|
3
|
-
require_relative 'tax/looks_up_tax_percentage_action'
|
|
4
|
-
require_relative 'tax/calculates_order_tax_action'
|
|
5
|
-
require_relative 'tax/provides_free_shipping_action'
|
|
6
|
-
|
|
7
|
-
describe CalculatesTax do
|
|
8
|
-
let(:order) { double('order') }
|
|
9
|
-
let(:ctx) { FunctionalLightService::Context.make(:user => nil) }
|
|
10
|
-
|
|
11
|
-
it "calls the actions in order" do
|
|
12
|
-
allow(FunctionalLightService::Context).to receive(:make)
|
|
13
|
-
.with({ :order => order })
|
|
14
|
-
.and_return(ctx)
|
|
15
|
-
|
|
16
|
-
allow(LooksUpTaxPercentageAction).to receive(:execute)
|
|
17
|
-
.with(ctx)
|
|
18
|
-
.and_return(ctx)
|
|
19
|
-
allow(CalculatesOrderTaxAction).to receive(:execute)
|
|
20
|
-
.with(ctx)
|
|
21
|
-
.and_return(ctx)
|
|
22
|
-
allow(ProvidesFreeShippingAction).to receive(:execute)
|
|
23
|
-
.with(ctx)
|
|
24
|
-
.and_return(ctx)
|
|
25
|
-
|
|
26
|
-
result = CalculatesTax.call(order)
|
|
27
|
-
|
|
28
|
-
expect(result).to eq(ctx)
|
|
29
|
-
end
|
|
30
|
-
end
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require_relative 'tax/looks_up_tax_percentage_action'
|
|
3
|
-
|
|
4
|
-
class TaxRange
|
|
5
|
-
extend FunctionalLightService::Action
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
describe LooksUpTaxPercentageAction do
|
|
9
|
-
let(:region) { double('region') }
|
|
10
|
-
let(:order) do
|
|
11
|
-
order = double('order')
|
|
12
|
-
allow(order).to receive_messages(:region => region)
|
|
13
|
-
allow(order).to receive_messages(:total => 200)
|
|
14
|
-
order
|
|
15
|
-
end
|
|
16
|
-
let(:context) do
|
|
17
|
-
FunctionalLightService::Context.make(:order => order)
|
|
18
|
-
end
|
|
19
|
-
let(:tax_percentage) { double('tax_percentage') }
|
|
20
|
-
let(:tax_ranges) { double('tax_ranges') }
|
|
21
|
-
|
|
22
|
-
context "when the tax_ranges were not found" do
|
|
23
|
-
it "sets the context to failure" do
|
|
24
|
-
allow(TaxRange).to receive(:for_region).with(region).and_return nil
|
|
25
|
-
LooksUpTaxPercentageAction.execute(context)
|
|
26
|
-
|
|
27
|
-
expect(context).to be_failure
|
|
28
|
-
expect(context.message).to eq "The tax ranges were not found"
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
context "when the tax_percentage is not found" do
|
|
33
|
-
it "sets the context to failure" do
|
|
34
|
-
allow(TaxRange).to receive(:for_region).with(region).and_return tax_ranges
|
|
35
|
-
allow(tax_ranges).to receive_messages(:for_total => nil)
|
|
36
|
-
|
|
37
|
-
LooksUpTaxPercentageAction.execute(context)
|
|
38
|
-
|
|
39
|
-
expect(context).to be_failure
|
|
40
|
-
expect(context.message).to eq "The tax percentage was not found"
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
context "when the tax_percentage is found" do
|
|
45
|
-
it "sets the tax_percentage in context" do
|
|
46
|
-
allow(TaxRange).to receive(:for_region).with(region).and_return tax_ranges
|
|
47
|
-
allow(tax_ranges).to receive_messages(:for_total => 25)
|
|
48
|
-
|
|
49
|
-
LooksUpTaxPercentageAction.execute(context)
|
|
50
|
-
|
|
51
|
-
expect(context).to be_success
|
|
52
|
-
expect(context.fetch(:tax_percentage)).to eq 25
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
require_relative 'tax/provides_free_shipping_action'
|
|
3
|
-
|
|
4
|
-
describe ProvidesFreeShippingAction do
|
|
5
|
-
let(:order) { double('order') }
|
|
6
|
-
let(:ctx) { { :order => order } }
|
|
7
|
-
|
|
8
|
-
context "when the order total with tax is > 200" do
|
|
9
|
-
specify "order gets free shipping" do
|
|
10
|
-
allow(order).to receive_messages(:total_with_tax => 201)
|
|
11
|
-
expect(order).to receive(:provide_free_shipping!)
|
|
12
|
-
|
|
13
|
-
ProvidesFreeShippingAction.execute(ctx)
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
context "when the order total with tax is <= 200" do
|
|
18
|
-
specify "order does not get free shipping" do
|
|
19
|
-
allow(order).to receive_messages(:total_with_tax => 200)
|
|
20
|
-
expect(order).not_to receive(:provide_free_shipping!)
|
|
21
|
-
|
|
22
|
-
ProvidesFreeShippingAction.execute(ctx)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
class LooksUpTaxPercentageAction
|
|
2
|
-
extend FunctionalLightService::Action
|
|
3
|
-
|
|
4
|
-
expects :order
|
|
5
|
-
promises :tax_percentage
|
|
6
|
-
|
|
7
|
-
executed do |ctx|
|
|
8
|
-
tax_ranges = TaxRange.for_region(ctx.order.region)
|
|
9
|
-
ctx.tax_percentage = 0
|
|
10
|
-
|
|
11
|
-
next ctx if object_is_nil?(tax_ranges, ctx, 'The tax ranges were not found')
|
|
12
|
-
|
|
13
|
-
ctx.tax_percentage = tax_ranges.for_total(ctx.order.total)
|
|
14
|
-
|
|
15
|
-
error_message = 'The tax percentage was not found'
|
|
16
|
-
next ctx if object_is_nil?(ctx.tax_percentage, ctx, error_message)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def self.object_is_nil?(object, ctx, message)
|
|
20
|
-
if object.nil?
|
|
21
|
-
ctx.fail!(message)
|
|
22
|
-
return true
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
false
|
|
26
|
-
end
|
|
27
|
-
private_class_method :object_is_nil?
|
|
28
|
-
end
|