functional-light-service 6.1.0 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/lib/functional-light-service.rb +6 -31
  3. metadata +15 -297
  4. data/.github/workflows/project-build.yml +0 -71
  5. data/.gitignore +0 -22
  6. data/.rspec +0 -3
  7. data/.rubocop.yml +0 -101
  8. data/.solargraph.yml +0 -11
  9. data/AUDIT-functional-light-service.md +0 -352
  10. data/Appraisals +0 -7
  11. data/CHANGELOG.md +0 -273
  12. data/CODE_OF_CONDUCT.md +0 -22
  13. data/Gemfile +0 -4
  14. data/LICENSE +0 -22
  15. data/README.md +0 -1578
  16. data/Rakefile +0 -12
  17. data/VERSION +0 -1
  18. data/audit/bench.rb +0 -99
  19. data/audit/verify_findings.rb +0 -172
  20. data/functional-light-service.gemspec +0 -33
  21. data/gemfiles/dry_inflector_0_2_1.gemfile +0 -5
  22. data/gemfiles/i18n_1_8_11.gemfile +0 -5
  23. data/lib/functional-light-service/action.rb +0 -97
  24. data/lib/functional-light-service/configuration.rb +0 -26
  25. data/lib/functional-light-service/context/key_verifier.rb +0 -124
  26. data/lib/functional-light-service/context.rb +0 -195
  27. data/lib/functional-light-service/deprecations.rb +0 -26
  28. data/lib/functional-light-service/errors.rb +0 -8
  29. data/lib/functional-light-service/functional/enum.rb +0 -286
  30. data/lib/functional-light-service/functional/maybe.rb +0 -21
  31. data/lib/functional-light-service/functional/monad.rb +0 -77
  32. data/lib/functional-light-service/functional/null.rb +0 -88
  33. data/lib/functional-light-service/functional/option.rb +0 -100
  34. data/lib/functional-light-service/functional/result.rb +0 -129
  35. data/lib/functional-light-service/functional/sequencer.rb +0 -144
  36. data/lib/functional-light-service/localization_adapter.rb +0 -48
  37. data/lib/functional-light-service/organizer/execute.rb +0 -16
  38. data/lib/functional-light-service/organizer/iterate.rb +0 -30
  39. data/lib/functional-light-service/organizer/reduce_if.rb +0 -19
  40. data/lib/functional-light-service/organizer/reduce_until.rb +0 -22
  41. data/lib/functional-light-service/organizer/scoped_reducable.rb +0 -15
  42. data/lib/functional-light-service/organizer/with_callback.rb +0 -28
  43. data/lib/functional-light-service/organizer/with_reducer.rb +0 -81
  44. data/lib/functional-light-service/organizer/with_reducer_factory.rb +0 -20
  45. data/lib/functional-light-service/organizer/with_reducer_log_decorator.rb +0 -110
  46. data/lib/functional-light-service/organizer.rb +0 -114
  47. data/lib/functional-light-service/testing/context_factory.rb +0 -48
  48. data/lib/functional-light-service/testing.rb +0 -3
  49. data/lib/functional-light-service/version.rb +0 -5
  50. data/resources/fail_actions.png +0 -0
  51. data/resources/light-service.png +0 -0
  52. data/resources/organizer_and_actions.png +0 -0
  53. data/resources/skip_actions.png +0 -0
  54. data/spec/acceptance/add_numbers_spec.rb +0 -11
  55. data/spec/acceptance/after_actions_spec.rb +0 -87
  56. data/spec/acceptance/around_each_spec.rb +0 -19
  57. data/spec/acceptance/before_actions_spec.rb +0 -115
  58. data/spec/acceptance/custom_log_from_organizer_spec.rb +0 -61
  59. data/spec/acceptance/deprecation_warnings_spec.rb +0 -82
  60. data/spec/acceptance/fail_spec.rb +0 -52
  61. data/spec/acceptance/log_from_organizer_spec.rb +0 -154
  62. data/spec/acceptance/message_localization_spec.rb +0 -119
  63. data/spec/acceptance/organizer/add_aliases_spec.rb +0 -28
  64. data/spec/acceptance/organizer/add_to_context_spec.rb +0 -30
  65. data/spec/acceptance/organizer/around_each_with_reduce_if_spec.rb +0 -42
  66. data/spec/acceptance/organizer/context_failure_and_skipping_spec.rb +0 -68
  67. data/spec/acceptance/organizer/execute_spec.rb +0 -46
  68. data/spec/acceptance/organizer/iterate_spec.rb +0 -44
  69. data/spec/acceptance/organizer/reduce_if_spec.rb +0 -89
  70. data/spec/acceptance/organizer/reduce_until_spec.rb +0 -49
  71. data/spec/acceptance/organizer/with_callback_spec.rb +0 -113
  72. data/spec/acceptance/organizer_entry_point_spec.rb +0 -35
  73. data/spec/acceptance/rollback_spec.rb +0 -183
  74. data/spec/acceptance/testing/context_factory_spec.rb +0 -54
  75. data/spec/action_expected_keys_spec.rb +0 -63
  76. data/spec/action_expects_and_promises_spec.rb +0 -97
  77. data/spec/action_promised_keys_spec.rb +0 -126
  78. data/spec/action_spec.rb +0 -97
  79. data/spec/context/inspect_spec.rb +0 -42
  80. data/spec/context_spec.rb +0 -289
  81. data/spec/examples/amount_spec.rb +0 -77
  82. data/spec/examples/controller_spec.rb +0 -63
  83. data/spec/examples/validate_address_spec.rb +0 -38
  84. data/spec/lib/deterministic/class_mixin_spec.rb +0 -24
  85. data/spec/lib/deterministic/currify_spec.rb +0 -90
  86. data/spec/lib/deterministic/monad_axioms.rb +0 -46
  87. data/spec/lib/deterministic/monad_spec.rb +0 -47
  88. data/spec/lib/deterministic/null_spec.rb +0 -65
  89. data/spec/lib/deterministic/option_spec.rb +0 -140
  90. data/spec/lib/deterministic/result/failure_spec.rb +0 -65
  91. data/spec/lib/deterministic/result/result_map_spec.rb +0 -155
  92. data/spec/lib/deterministic/result/result_shared.rb +0 -25
  93. data/spec/lib/deterministic/result/success_spec.rb +0 -41
  94. data/spec/lib/deterministic/result_spec.rb +0 -63
  95. data/spec/lib/deterministic/sequencer_spec.rb +0 -506
  96. data/spec/lib/edge_cases_spec.rb +0 -156
  97. data/spec/lib/enum_spec.rb +0 -114
  98. data/spec/lib/native_pattern_matching_spec.rb +0 -74
  99. data/spec/localization_adapter_spec.rb +0 -83
  100. data/spec/organizer/with_reducer_spec.rb +0 -56
  101. data/spec/organizer_key_aliases_spec.rb +0 -29
  102. data/spec/organizer_spec.rb +0 -115
  103. data/spec/readme_spec.rb +0 -45
  104. data/spec/sample/calculates_order_tax_action_spec.rb +0 -16
  105. data/spec/sample/calculates_tax_spec.rb +0 -30
  106. data/spec/sample/looks_up_tax_percentage_action_spec.rb +0 -55
  107. data/spec/sample/provides_free_shipping_action_spec.rb +0 -25
  108. data/spec/sample/tax/calculates_order_tax_action.rb +0 -10
  109. data/spec/sample/tax/calculates_tax.rb +0 -11
  110. data/spec/sample/tax/looks_up_tax_percentage_action.rb +0 -28
  111. data/spec/sample/tax/provides_free_shipping_action.rb +0 -11
  112. data/spec/spec_helper.rb +0 -29
  113. data/spec/support.rb +0 -1
  114. data/spec/test_doubles.rb +0 -628
  115. data/spec/testing/context_factory/iterate_spec.rb +0 -39
  116. data/spec/testing/context_factory/reduce_if_spec.rb +0 -40
  117. data/spec/testing/context_factory/reduce_until_spec.rb +0 -40
  118. data/spec/testing/context_factory/with_callback_spec.rb +0 -38
  119. data/spec/testing/context_factory_spec.rb +0 -76
@@ -1,38 +0,0 @@
1
- require 'spec_helper'
2
-
3
- # A Unit of Work for validating an address
4
- module ValidateAddress
5
- extend FunctionalLightService::Prelude::Result
6
-
7
- def self.call(candidate)
8
- errors = {}
9
- errors[:street] = "Street cannot be empty" unless candidate.key? :street
10
- errors[:city] = "Street cannot be empty" unless candidate.key? :city
11
- errors[:postal] = "Street cannot be empty" unless candidate.key? :postal
12
-
13
- errors.empty? ? Success(candidate) : Failure(errors)
14
- end
15
- end
16
-
17
- describe ValidateAddress do
18
- include FunctionalLightService
19
-
20
- subject { ValidateAddress.call(candidate) }
21
- context 'sunny day' do
22
- let(:candidate) do
23
- { :title => "Hobbiton",
24
- :street => "501 Buckland Rd",
25
- :city => "Matamata",
26
- :postal => "3472",
27
- :country => "nz" }
28
- end
29
- specify { expect(subject).to be_a FunctionalLightService::Result::Success }
30
- specify { expect(subject.value).to eq candidate }
31
- end
32
-
33
- context 'empty data' do
34
- let(:candidate) { {} }
35
- specify { expect(subject).to be_a FunctionalLightService::Result::Failure }
36
- specify { expect(subject.value).to include(:street, :city, :postal) }
37
- end
38
- end
@@ -1,24 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe 'Class Mixin' do
4
- describe 'try' do
5
- module MyApp
6
- class Thing
7
- include FunctionalLightService::Prelude::Result
8
-
9
- def run
10
- Success(11) >> method(:double)
11
- end
12
-
13
- def double(num)
14
- Success(num * 2)
15
- end
16
- end
17
- end
18
-
19
- it "cleanly mixes into a class" do
20
- result = MyApp::Thing.new.run
21
- expect(result).to eq FunctionalLightService::Result::Success.new(22)
22
- end
23
- end
24
- end
@@ -1,90 +0,0 @@
1
- require 'spec_helper'
2
- require 'pry'
3
-
4
- module FunctionalLightService
5
- module Currify
6
- module ClassMethods
7
- def currify(*names)
8
- names.each do |name|
9
- unbound_method = instance_method(name)
10
-
11
- define_method(name) do |*args|
12
- curried_method = unbound_method.bind(self).to_proc.curry
13
- curried_method[*args]
14
- end
15
- end
16
- end
17
- end
18
-
19
- def self.included(curried)
20
- curried.extend ClassMethods
21
- end
22
- end
23
- end
24
-
25
- class Object
26
- class Proc
27
- def self.compose(f, g)
28
- ->(*args) { f[g[*args]] }
29
- end
30
-
31
- # rubocop:disable Naming/BinaryOperatorParameterName
32
- # Compose left to right
33
- def |(g)
34
- Proc.compose(g, self)
35
- end
36
-
37
- # Compose right to left
38
- def *(g)
39
- Proc.compose(self, g)
40
- end
41
- # rubocop:enable Naming/BinaryOperatorParameterName
42
- end
43
- end
44
-
45
- class Booking
46
- include FunctionalLightService::Currify
47
- include FunctionalLightService::Prelude::Result
48
-
49
- def initialize(deps)
50
- @deps = deps
51
- end
52
-
53
- def build(id, format)
54
- validate(id) | req | find | render(format)
55
-
56
- validate(id) | request(id) | find
57
- end
58
-
59
- def validate(id)
60
- Success(id)
61
- end
62
-
63
- def req(a, id)
64
- Success(:id => id + a)
65
- end
66
-
67
- def find(req)
68
- Success(:found => req)
69
- end
70
-
71
- def render(format, req)
72
- Success("rendered in #{format}: #{req[:found]}")
73
- end
74
-
75
- currify :find, :render, :req
76
- end
77
-
78
- describe "Pref" do
79
- include FunctionalLightService::Prelude::Result
80
-
81
- it "does something" do
82
- b = Booking.new(1)
83
- actual = b.validate(1) >> b.req(2) >> b.find >> b.render(:html)
84
-
85
- # il formato di Hash#to_s cambia tra Ruby 3.3 e 3.4: costruiamo l'atteso dinamicamente
86
- rendered_params = { :id => 3 }
87
- expected = FunctionalLightService::Result::Success.new("rendered in html: #{rendered_params}")
88
- expect(actual).to eq expected
89
- end
90
- end
@@ -1,46 +0,0 @@
1
- shared_examples 'a Monad' do
2
- describe 'axioms' do
3
- it '1st monadic law: left-identity' do
4
- f = ->(value) { monad.new(value + 1) }
5
- expect(
6
- monad.new(1).bind do |value|
7
- f.call(value)
8
- end
9
- ).to eq f.call(1)
10
- end
11
-
12
- it '2nd monadic law: right-identy - new and bind do not change the value' do
13
- expect(
14
- monad.new(1).bind do |value|
15
- monad.new(value)
16
- end
17
- ).to eq monad.new(1)
18
- end
19
-
20
- it '3rd monadic law: associativity' do
21
- f = ->(value) { monad.new(value + 1) }
22
- g = ->(value) { monad.new(value + 100) }
23
-
24
- id1 = monad.new(1).bind { |a| f.call(a) }.bind { |b| g.call(b) }
25
-
26
- id2 = monad.new(1).bind do |a|
27
- f.call(a).bind do |b|
28
- g.call(b)
29
- end
30
- end
31
-
32
- expect(id1).to eq id2
33
- end
34
-
35
- it '#bind must return a monad' do
36
- expect(monad.new(1).bind { |v| monad.new(v) }).to eq monad.new(1)
37
- # rubocop:disable Lint/EmptyBlock
38
- expect { monad.new(1).bind {} }.to raise_error(FunctionalLightService::Monad::NotMonadError)
39
- # rubocop:enable Lint/EmptyBlock
40
- end
41
-
42
- it '#new must return a monad' do
43
- expect(monad.new(1)).to be_a monad
44
- end
45
- end
46
- end
@@ -1,47 +0,0 @@
1
- require 'spec_helper'
2
- require_relative 'monad_axioms'
3
-
4
- describe FunctionalLightService::Monad do
5
- class Identity
6
- include FunctionalLightService::Monad
7
- end
8
-
9
- let(:monad) { Identity }
10
- it_behaves_like 'a Monad' do
11
- # let(:monad) { monad }
12
- end
13
-
14
- specify { expect(Identity.new(1).inspect).to eq 'Identity(1)' }
15
- specify { expect(Identity.new(1).to_s).to eq '1' }
16
- specify { expect(Identity.new(nil).inspect).to eq 'Identity(nil)' }
17
- specify { expect(Identity.new(nil).to_s).to eq '' }
18
- specify { expect(Identity.new([1, 2]).fmap(&:to_s)).to eq Identity.new("[1, 2]") }
19
- specify { expect(Identity.new(1).fmap { |v| v + 2 }).to eq Identity.new(3) }
20
- specify { expect(Identity.new('foo').fmap(&:upcase)).to eq Identity.new('FOO') }
21
-
22
- context '#bind' do
23
- it "raises an error if the passed function does not return a monad of the same class" do
24
- # rubocop:disable Lint/EmptyBlock
25
- expect { Identity.new(1).bind {} }.to \
26
- raise_error(FunctionalLightService::Monad::NotMonadError)
27
- # rubocop:enable Lint/EmptyBlock
28
- end
29
- specify { expect(Identity.new(1).bind { |value| Identity.new(value) }).to eq Identity.new(1) }
30
-
31
- it "passes the monad class, this is ruby-fu?!" do
32
- Identity.new(1)
33
- .bind do |v|
34
- expect(monad).to eq Identity
35
- monad.new(v)
36
- end
37
- end
38
-
39
- specify do
40
- expect(
41
- monad.new(1).bind { |value| monad.new(value + 1) }
42
- ).to eq Identity.new(2)
43
- end
44
- end
45
- specify { expect(Identity.new(Identity.new(1))).to eq Identity.new(1) }
46
- end
47
-
@@ -1,65 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Null do
4
- it "Null is a Singleton" do
5
- expect(Null.instance).to be_a Null
6
- expect { Null.new }.to raise_error(NoMethodError, /private method [`']new'/)
7
- end
8
-
9
- it "respond_to? accepts the standard two-argument form" do
10
- expect(Null.instance.respond_to?(:anything, true)).to be(true)
11
- expect(Null.instance.respond_to?(:anything)).to be(true)
12
- end
13
-
14
- it "explicit conversions" do
15
- expect(Null.to_s).to eq 'Null'
16
- expect(Null.inspect).to eq 'Null'
17
- end
18
-
19
- it "answer if Null is null" do
20
- expect(Null.null?).to eq true
21
- end
22
-
23
- it "answer if Null is some" do
24
- expect(Null.some?).to eq false
25
- end
26
-
27
- it "compares to Null" do
28
- # rubocop:disable Style/CaseEquality
29
- expect(Null === Null.instance).to be_truthy
30
- expect(Null.instance === Null).to be_truthy
31
- expect(Null.instance).to eq Null
32
- expect(Null).to eq Null.instance
33
- expect(1).not_to be Null
34
- expect(1).not_to be Null.instance
35
- expect(Null.instance).not_to be 1
36
- expect(Null).not_to be 1
37
- expect(Null.instance).not_to be_nil
38
- expect(Null).not_to be_nil
39
- # rubocop:enable Style/CaseEquality
40
- end
41
-
42
- it "implicit conversions" do
43
- null = Null.instance
44
- expect(null.to_str).to eq ""
45
- expect(null.to_ary).to eq []
46
- # rubocop:disable Style/StringConcatenation
47
- expect("" + null).to eq ""
48
- # rubocop:enable Style/StringConcatenation
49
-
50
- a, b, c = null
51
- expect(a).to be_nil
52
- expect(b).to be_nil
53
- expect(c).to be_nil
54
- end
55
-
56
- it "mimicks other classes and returns Null for their public methods" do
57
- class UnderMimickTest
58
- def test; end
59
- end
60
-
61
- mimick = Null.mimic(UnderMimickTest)
62
- expect(mimick.test).to be_null
63
- expect { mimick.i_dont_exist }.to raise_error(NoMethodError)
64
- end
65
- end
@@ -1,140 +0,0 @@
1
- require 'spec_helper'
2
-
3
- include FunctionalLightService::Prelude::Option
4
-
5
- describe FunctionalLightService::Option do
6
- it "Some cannot wrap nil" do
7
- expect { described_class::Some.new(nil) }
8
- .to raise_error(ArgumentError, /use None instead/)
9
- end
10
-
11
- specify { expect(described_class::Some.new(0)).to be_a described_class::Some }
12
- specify { expect(described_class::Some.new(0)).to be_a described_class }
13
- specify { expect(described_class::Some.new(0)).to eq Some(0) }
14
-
15
- specify { expect(described_class::None.new).to eq described_class::None.new }
16
- specify { expect(described_class::None.new).to be_a described_class::None }
17
- specify { expect(described_class::None.new).to be_a described_class }
18
- specify { expect(described_class::None.new).to eq None }
19
-
20
- it "join" do
21
- expect(Some(Some(1))).to eq Some(1)
22
- end
23
-
24
- it "fmap" do
25
- expect(Some(1).fmap { |n| n + 1 }).to eq Some(2)
26
- expect(None.fmap { |n| n + 1 }).to eq None
27
- end
28
-
29
- it "map" do
30
- expect(Some(1).map { |n| Some(n + 1) }).to eq Some(2)
31
- expect(Some(1).map { |_n| None }).to eq None
32
- expect(None.map { |n| Some(n + 1) }).to eq None
33
- end
34
-
35
- it "some?" do
36
- expect(Some(1).some?).to be_truthy
37
- expect(None.some?).to be_falsey
38
- end
39
-
40
- it "none?" do
41
- expect(None.none?).to be_truthy
42
- expect(Some(1).none?).to be_falsey
43
- end
44
-
45
- it "value" do
46
- expect(Some(1).value).to eq 1
47
- expect { None.value }.to raise_error NoMethodError
48
- end
49
-
50
- it "value_or" do
51
- expect(Some(1).value_or(2)).to eq 1
52
- expect(None.value_or(0)).to eq 0
53
- end
54
-
55
- it "+" do
56
- expect(Some([1]) + None).to eq Some([1])
57
- expect(Some(1) + None + None).to eq Some(1)
58
- expect(Some(1) + Some(1)).to eq Some(2)
59
- expect(None + Some(1)).to eq Some(1)
60
- expect(None + None + Some(1)).to eq Some(1)
61
- expect(None + None + Some(1) + None).to eq Some(1)
62
- expect(None + Some(:foo => 1)).to eq Some(:foo => 1)
63
- expect(Some([1]) + Some([1])).to eq Some([1, 1])
64
- expect { Some([1]) + Some(1) }.to raise_error TypeError
65
- end
66
-
67
- it "inspect" do
68
- expect(Some(1).inspect).to eq "Some(1)"
69
- expect(described_class::None.new.inspect).to eq "None"
70
- end
71
-
72
- it "to_s" do
73
- expect(Some(1).to_s).to eq "1"
74
- expect(described_class::None.new.to_s).to eq ""
75
- end
76
-
77
- it "match" do
78
- expect(
79
- # rubocop:disable Lint/UnusedBlockArgument
80
- # rubocop:disable Lint/EmptyBlock
81
- Some(0).match do
82
- Some(where { s == 1 }) { |s| 99 }
83
- Some(where { s == 0 }) { |s| s + 1 }
84
- None() {}
85
- end
86
- ).to eq 1
87
-
88
- expect(
89
- Some(1).match do
90
- None() { 0 }
91
- Some() { |s| 1 }
92
- end
93
- ).to eq 1
94
-
95
- expect(
96
- Some(1).match do
97
- None() { 0 }
98
- Some(where { s.is_a? Integer }) { |s| 1 }
99
- end
100
- # rubocop:enable Lint/UnusedBlockArgument
101
- # rubocop:enable Lint/EmptyBlock
102
- ).to eq 1
103
-
104
- expect(
105
- None.match do
106
- None() { 0 }
107
- Some() { 1 }
108
- end
109
- ).to eq 0
110
- end
111
-
112
- it "nil?" do
113
- expect(described_class.some?(nil)).to eq None
114
- expect(described_class.some?(1)).to be_some
115
- expect(described_class.some?(1)).to eq Some(1)
116
- end
117
-
118
- it "any?" do
119
- expect(described_class.any?(nil)).to be_none
120
- expect(described_class.any?(None)).to be_none
121
- expect(described_class.any?("")).to be_none
122
- expect(described_class.any?([])).to be_none
123
- expect(described_class.any?({})).to be_none
124
- expect(described_class.any?([1])).to eq Some([1])
125
- expect(described_class.any?(:foo => 1)).to eq Some(:foo => 1)
126
- expect(described_class.any?(1)).to eq Some(1)
127
- end
128
-
129
- it "try!" do
130
- expect(described_class.try! { raise "error" }).to be_none
131
- end
132
- end
133
-
134
- require_relative 'monad_axioms'
135
-
136
- describe FunctionalLightService::Option::Some do
137
- it_behaves_like 'a Monad' do
138
- let(:monad) { described_class }
139
- end
140
- end
@@ -1,65 +0,0 @@
1
- require 'spec_helper'
2
- require_relative '../monad_axioms'
3
- require_relative 'result_shared'
4
-
5
- describe FunctionalLightService::Result::Failure do
6
- include FunctionalLightService::Prelude::Result
7
-
8
- it_behaves_like 'a Monad' do
9
- let(:monad) { described_class }
10
- end
11
-
12
- subject { described_class.new(1) }
13
-
14
- specify { expect(subject).to be_an_instance_of described_class }
15
- specify { expect(subject).to be_failure }
16
- specify { expect(subject).not_to be_success }
17
- specify { expect(subject.success?).to be_falsey }
18
- specify { expect(subject.failure?).to be_truthy }
19
-
20
- specify { expect(subject).to be_an_instance_of described_class }
21
- specify { expect(subject).to eq(described_class.new(1)) }
22
- specify { expect(subject.fmap { |v| v + 1 }).to eq Failure(2) }
23
- specify { expect(subject.map { |v| Success(v + 1) }).to eq Failure(1) }
24
- specify { expect(subject.map_err { |v| Success(v + 1) }).to eq Success(2) }
25
- specify do
26
- expect(subject.pipe { |v| raise RuntimeError unless v == Failure(1) }).to eq Failure(1)
27
- end
28
-
29
- specify { expect(subject.or(Success(2))).to eq Success(2) }
30
- specify { expect(subject.or(Failure(2))).to eq Failure(2) }
31
- specify { expect(subject.or_else { Success(2) }).to eq Success(2) }
32
- specify { expect(subject.or_else { Failure(2) }).to eq Failure(2) }
33
-
34
- specify { expect(subject.and(Success(2))).to eq Failure(1) }
35
- specify { expect(subject.and_then { Success(2) }).to eq Failure(1) }
36
-
37
- it_behaves_like 'Result' do
38
- let(:result) { described_class }
39
- end
40
-
41
- it "#or" do
42
- expect(Success(1).or(Failure(2))).to eq Success(1)
43
- expect(Failure(1).or(Success(2))).to eq Success(2)
44
- expect { Failure(1).or(2) }.to raise_error(FunctionalLightService::Monad::NotMonadError)
45
- end
46
-
47
- it "#or_else" do
48
- expect(Success(1).or_else { Failure(2) }).to eq Success(1)
49
- expect(Failure(1).or_else { |v| Success(v + 1) }).to eq Success(2)
50
- expect { Failure(1).or_else { 2 } }.to raise_error(FunctionalLightService::Monad::NotMonadError)
51
- end
52
-
53
- it "#and" do
54
- expect(Success(1).and(Success(2))).to eq Success(2)
55
- expect(Failure(1).and(Success(2))).to eq Failure(1)
56
- expect { Success(1).and(2) }.to raise_error(FunctionalLightService::Monad::NotMonadError)
57
- end
58
-
59
- it "#and_then" do
60
- expect(Success(1).and_then { Success(2) }).to eq Success(2)
61
- expect(Failure(1).and_then { Success(2) }).to eq Failure(1)
62
- expect { Success(1).and_then { 2 } }.to \
63
- raise_error(FunctionalLightService::Monad::NotMonadError)
64
- end
65
- end
@@ -1,155 +0,0 @@
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
@@ -1,25 +0,0 @@
1
- shared_examples 'Result' do
2
- let(:result_name) { described_class.name.split("::")[-1] }
3
- specify { expect(subject.value).to eq 1 }
4
- specify { expect(result.new(subject)).to eq result.new(1) }
5
-
6
- it "#fmap" do
7
- expect(result.new(1).fmap { |e| e + 1 }).to eq result.new(2)
8
- end
9
-
10
- it "#bind" do
11
- expect(result.new(1).bind { |v| result.new(v + 1) }).to eq result.new(2)
12
- end
13
-
14
- it "#to_s" do
15
- expect(result.new(1).to_s).to eq "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)
18
- end
19
-
20
- it "#inspect" do
21
- expect(result.new(1).inspect).to eq "#{result_name}(1)"
22
- expect(result.new(:a => 1).inspect).to eq "#{result_name}(#{{ :a => 1 }.inspect})"
23
- end
24
- end
25
-