functional-light-service 0.5.4 → 6.1.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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/project-build.yml +35 -11
  3. data/.rubocop.yml +101 -160
  4. data/AUDIT-functional-light-service.md +352 -0
  5. data/CHANGELOG.md +45 -0
  6. data/README.md +88 -2
  7. data/audit/bench.rb +99 -0
  8. data/audit/verify_findings.rb +172 -0
  9. data/functional-light-service.gemspec +15 -21
  10. data/lib/functional-light-service/action.rb +97 -101
  11. data/lib/functional-light-service/configuration.rb +26 -24
  12. data/lib/functional-light-service/context/key_verifier.rb +124 -118
  13. data/lib/functional-light-service/context.rb +63 -20
  14. data/lib/functional-light-service/deprecations.rb +26 -0
  15. data/lib/functional-light-service/errors.rb +8 -6
  16. data/lib/functional-light-service/functional/enum.rb +286 -250
  17. data/lib/functional-light-service/functional/maybe.rb +21 -15
  18. data/lib/functional-light-service/functional/monad.rb +77 -66
  19. data/lib/functional-light-service/functional/null.rb +88 -74
  20. data/lib/functional-light-service/functional/option.rb +100 -97
  21. data/lib/functional-light-service/functional/result.rb +129 -116
  22. data/lib/functional-light-service/functional/sequencer.rb +144 -0
  23. data/lib/functional-light-service/localization_adapter.rb +48 -47
  24. data/lib/functional-light-service/organizer/execute.rb +16 -14
  25. data/lib/functional-light-service/organizer/iterate.rb +30 -25
  26. data/lib/functional-light-service/organizer/reduce_if.rb +19 -17
  27. data/lib/functional-light-service/organizer/reduce_until.rb +22 -20
  28. data/lib/functional-light-service/organizer/scoped_reducable.rb +15 -13
  29. data/lib/functional-light-service/organizer/with_callback.rb +28 -26
  30. data/lib/functional-light-service/organizer/with_reducer.rb +81 -77
  31. data/lib/functional-light-service/organizer/with_reducer_factory.rb +20 -18
  32. data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +110 -108
  33. data/lib/functional-light-service/organizer.rb +114 -114
  34. data/lib/functional-light-service/testing/context_factory.rb +48 -42
  35. data/lib/functional-light-service/testing.rb +3 -1
  36. data/lib/functional-light-service/version.rb +5 -3
  37. data/lib/functional-light-service.rb +31 -28
  38. data/spec/acceptance/after_actions_spec.rb +87 -71
  39. data/spec/acceptance/before_actions_spec.rb +115 -98
  40. data/spec/acceptance/custom_log_from_organizer_spec.rb +61 -60
  41. data/spec/acceptance/deprecation_warnings_spec.rb +82 -0
  42. data/spec/acceptance/fail_spec.rb +52 -50
  43. data/spec/acceptance/message_localization_spec.rb +119 -118
  44. data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +68 -65
  45. data/spec/acceptance/organizer/reduce_if_spec.rb +89 -89
  46. data/spec/acceptance/organizer/with_callback_spec.rb +113 -110
  47. data/spec/acceptance/{not_having_call_method_warning_spec.rb → organizer_entry_point_spec.rb} +10 -7
  48. data/spec/acceptance/rollback_spec.rb +183 -132
  49. data/spec/action_expects_and_promises_spec.rb +97 -93
  50. data/spec/action_promised_keys_spec.rb +126 -122
  51. data/spec/context_spec.rb +289 -197
  52. data/spec/examples/controller_spec.rb +63 -63
  53. data/spec/examples/validate_address_spec.rb +38 -37
  54. data/spec/lib/deterministic/currify_spec.rb +90 -88
  55. data/spec/lib/deterministic/null_spec.rb +6 -1
  56. data/spec/lib/deterministic/option_spec.rb +140 -137
  57. data/spec/lib/deterministic/result/result_map_spec.rb +155 -154
  58. data/spec/lib/deterministic/result/result_shared.rb +3 -2
  59. data/spec/lib/deterministic/result_spec.rb +2 -2
  60. data/spec/lib/deterministic/sequencer_spec.rb +506 -0
  61. data/spec/lib/edge_cases_spec.rb +156 -0
  62. data/spec/lib/enum_spec.rb +1 -1
  63. data/spec/lib/native_pattern_matching_spec.rb +74 -0
  64. data/spec/organizer_spec.rb +115 -114
  65. data/spec/readme_spec.rb +45 -47
  66. data/spec/sample/calculates_order_tax_action_spec.rb +16 -16
  67. data/spec/sample/calculates_tax_spec.rb +1 -1
  68. data/spec/sample/looks_up_tax_percentage_action_spec.rb +55 -55
  69. data/spec/sample/tax/calculates_order_tax_action.rb +10 -9
  70. data/spec/sample/tax/looks_up_tax_percentage_action.rb +28 -27
  71. data/spec/sample/tax/provides_free_shipping_action.rb +11 -10
  72. data/spec/spec_helper.rb +6 -0
  73. data/spec/test_doubles.rb +628 -599
  74. data/spec/testing/context_factory_spec.rb +21 -0
  75. metadata +48 -162
  76. data/lib/functional-light-service/organizer/verify_call_method_exists.rb +0 -29
  77. data/spec/acceptance/include_warning_spec.rb +0 -29
@@ -1,154 +1,155 @@
1
- require 'spec_helper'
2
-
3
- describe FunctionalLightService::Result do
4
- include FunctionalLightService::Prelude::Result
5
-
6
- context ">> (map)" do
7
- specify { expect(Success(0).map { |n| Success(n + 1) }).to eq Success(1) }
8
- specify { expect(Failure(0).map { |n| Success(n + 1) }).to eq Failure(0) }
9
-
10
- it "Failure stops execution" do
11
- class ChainUnderTest
12
- include FunctionalLightService::Prelude::Result
13
- alias :m :method
14
-
15
- def call
16
- init >>
17
- m(:validate) >>
18
- m(:send) >>
19
- m(:parse)
20
- end
21
-
22
- def init
23
- Success(:step => 1)
24
- end
25
-
26
- def validate(i)
27
- i[:step] = i[:step] + 1
28
- Success(i)
29
- end
30
-
31
- def send(i)
32
- i[:step] = i[:step] + 1
33
- Failure("Error @ #{i.fetch(:step)}")
34
- end
35
-
36
- def parse(i)
37
- i[:step] = i[:step] + 1
38
- Success(i)
39
- end
40
- end
41
-
42
- test = ChainUnderTest.new
43
-
44
- expect(test.call).to eq Failure("Error @ 3")
45
- end
46
-
47
- it "expects an Result" do
48
- def returns_non_result(_i)
49
- 2
50
- end
51
-
52
- expect { Success(1) >> method(:returns_non_result) }.to \
53
- raise_error(FunctionalLightService::Monad::NotMonadError)
54
- end
55
-
56
- it "works with a block" do
57
- expect(
58
- Success(1).map { |i| Success(i + 1) }
59
- ).to eq Success(2)
60
- end
61
-
62
- it "works with a lambda" do
63
- expect(
64
- Success(1) >> ->(i) { Success(i + 1) }
65
- ).to eq Success(2)
66
- end
67
-
68
- it "does not catch exceptions" do
69
- expect do
70
- Success(1) >> ->(_i) { raise "error" }
71
- end.to raise_error(RuntimeError)
72
- end
73
- end
74
-
75
- context "using self as the context for success" do
76
- class SelfContextUnderTest
77
- include FunctionalLightService::Prelude::Result
78
-
79
- def call
80
- @step = 0
81
- Success(self)
82
- .map(&:validate)
83
- .map(&:build)
84
- .map(&:send)
85
- end
86
-
87
- def validate
88
- @step = 1
89
- Success(self)
90
- end
91
-
92
- def build
93
- @step = 2
94
- Success(self)
95
- end
96
-
97
- def send
98
- @step = 3
99
- Success(self)
100
- end
101
-
102
- def inspect
103
- "Step #{@step}"
104
- end
105
-
106
- # # def self.procify(*meths)
107
- # # meths.each do |m|
108
- # # new_m = "__#{m}__procified".to_sym
109
- # # alias new_m m
110
- # # define_method new_m do |ctx|
111
- # # method(m)
112
- # # end
113
- # # end
114
- # # end
115
-
116
- # procify :send
117
- end
118
-
119
- it "works" do
120
- test = SelfContextUnderTest.new.call
121
- expect(test).to be_a described_class::Success
122
- expect(test.inspect).to eq "Success(Step 3)"
123
- end
124
- end
125
-
126
- context "<< (pipe)" do
127
- it "ignores the output of pipe" do
128
- acc = "ctx: "
129
- log = ->(ctx) { acc += ctx.inspect }
130
-
131
- actual = Success(1).pipe(log).map { Success(2) }
132
- expect(actual).to eq Success(2)
133
- expect(acc).to eq "ctx: Success(1)"
134
- end
135
-
136
- it "works with <<" do
137
- log = ->(n) { n.value + 1 }
138
- foo = ->(n) { Success(n + 1) }
139
-
140
- Success(1) << log >> foo
141
- end
142
- end
143
-
144
- context ">= (try)" do
145
- it "try (>=) catches errors and wraps them as Failure" do
146
- def error(ctx)
147
- raise "error #{ctx}"
148
- end
149
-
150
- actual = Success(1) >= method(:error)
151
- expect(actual.inspect).to eq "Failure(#<RuntimeError: error 1>)"
152
- end
153
- end
154
- end
1
+ require 'spec_helper'
2
+
3
+ describe FunctionalLightService::Result do
4
+ include FunctionalLightService::Prelude::Result
5
+
6
+ context ">> (map)" do
7
+ specify { expect(Success(0).map { |n| Success(n + 1) }).to eq Success(1) }
8
+ specify { expect(Failure(0).map { |n| Success(n + 1) }).to eq Failure(0) }
9
+
10
+ it "Failure stops execution" do
11
+ class ChainUnderTest
12
+ include FunctionalLightService::Prelude::Result
13
+
14
+ alias :m :method
15
+
16
+ def call
17
+ init >>
18
+ m(:validate) >>
19
+ m(:send) >>
20
+ m(:parse)
21
+ end
22
+
23
+ def init
24
+ Success(:step => 1)
25
+ end
26
+
27
+ def validate(i)
28
+ i[:step] = i[:step] + 1
29
+ Success(i)
30
+ end
31
+
32
+ def send(i)
33
+ i[:step] = i[:step] + 1
34
+ Failure("Error @ #{i.fetch(:step)}")
35
+ end
36
+
37
+ def parse(i)
38
+ i[:step] = i[:step] + 1
39
+ Success(i)
40
+ end
41
+ end
42
+
43
+ test = ChainUnderTest.new
44
+
45
+ expect(test.call).to eq Failure("Error @ 3")
46
+ end
47
+
48
+ it "expects an Result" do
49
+ def returns_non_result(_i)
50
+ 2
51
+ end
52
+
53
+ expect { Success(1) >> method(:returns_non_result) }.to \
54
+ raise_error(FunctionalLightService::Monad::NotMonadError)
55
+ end
56
+
57
+ it "works with a block" do
58
+ expect(
59
+ Success(1).map { |i| Success(i + 1) }
60
+ ).to eq Success(2)
61
+ end
62
+
63
+ it "works with a lambda" do
64
+ expect(
65
+ Success(1) >> ->(i) { Success(i + 1) }
66
+ ).to eq Success(2)
67
+ end
68
+
69
+ it "does not catch exceptions" do
70
+ expect do
71
+ Success(1) >> ->(_i) { raise "error" }
72
+ end.to raise_error(RuntimeError)
73
+ end
74
+ end
75
+
76
+ context "using self as the context for success" do
77
+ class SelfContextUnderTest
78
+ include FunctionalLightService::Prelude::Result
79
+
80
+ def call
81
+ @step = 0
82
+ Success(self)
83
+ .map(&:validate)
84
+ .map(&:build)
85
+ .map(&:send)
86
+ end
87
+
88
+ def validate
89
+ @step = 1
90
+ Success(self)
91
+ end
92
+
93
+ def build
94
+ @step = 2
95
+ Success(self)
96
+ end
97
+
98
+ def send
99
+ @step = 3
100
+ Success(self)
101
+ end
102
+
103
+ def inspect
104
+ "Step #{@step}"
105
+ end
106
+
107
+ # # def self.procify(*meths)
108
+ # # meths.each do |m|
109
+ # # new_m = "__#{m}__procified".to_sym
110
+ # # alias new_m m
111
+ # # define_method new_m do |ctx|
112
+ # # method(m)
113
+ # # end
114
+ # # end
115
+ # # end
116
+
117
+ # procify :send
118
+ end
119
+
120
+ it "works" do
121
+ test = SelfContextUnderTest.new.call
122
+ expect(test).to be_a described_class::Success
123
+ expect(test.inspect).to eq "Success(Step 3)"
124
+ end
125
+ end
126
+
127
+ context "<< (pipe)" do
128
+ it "ignores the output of pipe" do
129
+ acc = "ctx: "
130
+ log = ->(ctx) { acc += ctx.inspect }
131
+
132
+ actual = Success(1).pipe(log).map { Success(2) }
133
+ expect(actual).to eq Success(2)
134
+ expect(acc).to eq "ctx: Success(1)"
135
+ end
136
+
137
+ it "works with <<" do
138
+ log = ->(n) { n.value + 1 }
139
+ foo = ->(n) { Success(n + 1) }
140
+
141
+ Success(1) << log >> foo
142
+ end
143
+ end
144
+
145
+ context ">= (try)" do
146
+ it "try (>=) catches errors and wraps them as Failure" do
147
+ def error(ctx)
148
+ raise "error #{ctx}"
149
+ end
150
+
151
+ actual = Success(1) >= method(:error)
152
+ expect(actual.inspect).to eq "Failure(#<RuntimeError: error 1>)"
153
+ end
154
+ end
155
+ end
@@ -13,12 +13,13 @@ shared_examples 'Result' do
13
13
 
14
14
  it "#to_s" do
15
15
  expect(result.new(1).to_s).to eq "1"
16
- expect(result.new(:a => 1).to_s).to eq "{:a=>1}"
16
+ # il formato di Hash#to_s/inspect cambia tra Ruby 3.3 e 3.4: costruiamo l'atteso dinamicamente
17
+ expect(result.new(:a => 1).to_s).to eq({ :a => 1 }.to_s)
17
18
  end
18
19
 
19
20
  it "#inspect" do
20
21
  expect(result.new(1).inspect).to eq "#{result_name}(1)"
21
- expect(result.new(:a => 1).inspect).to eq "#{result_name}({:a=>1})"
22
+ expect(result.new(:a => 1).inspect).to eq "#{result_name}(#{{ :a => 1 }.inspect})"
22
23
  end
23
24
  end
24
25
 
@@ -4,8 +4,8 @@ describe FunctionalLightService::Result do
4
4
  include FunctionalLightService::Prelude::Result
5
5
 
6
6
  it "can't call Result#new directly" do
7
- msg = "private method `new' called for FunctionalLightService::Result:Class"
8
- expect { described_class.new(1) }.to raise_error(NoMethodError, msg)
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
9
  end
10
10
 
11
11
  it "fmap" do