Skip to content

Commit

Permalink
Add the Given() addon
Browse files Browse the repository at this point in the history
  • Loading branch information
serradura committed Jan 2, 2024
1 parent f9ef26b commit 57c6888
Show file tree
Hide file tree
Showing 19 changed files with 734 additions and 16 deletions.
3 changes: 2 additions & 1 deletion lib/bcdd/result/config/switchers/addons.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ module Addons
].freeze

OPTIONS = {
continue: { default: false, affects: AFFECTS }
continue: { default: false, affects: AFFECTS },
given: { default: true, affects: AFFECTS }
}.transform_values!(&:freeze).freeze

def self.switcher
Expand Down
10 changes: 9 additions & 1 deletion lib/bcdd/result/context/expectations/mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,15 @@ module Continue
end
end

OPTIONS = { continue: Continue }.freeze
module Given
private def Given(*values)
value = values.map(&:to_h).reduce({}) { |acc, val| acc.merge(val) }

Success.new(type: :given, value: value, subject: self)
end
end

OPTIONS = { continue: Continue, given: Given }.freeze

def self.options(config_flags)
::BCDD::Result::Config::Options.addon(map: config_flags, from: OPTIONS)
Expand Down
10 changes: 9 additions & 1 deletion lib/bcdd/result/context/mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,15 @@ def Success(type, **value)
end
end

OPTIONS = { continue: Continue }.freeze
module Given
private def Given(*values)
value = values.map(&:to_h).reduce({}) { |acc, val| acc.merge(val) }

_ResultAs(Success, :given, value)
end
end

OPTIONS = { continue: Continue, given: Given }.freeze

def self.options(config_flags)
::BCDD::Result::Config::Options.addon(map: config_flags, from: OPTIONS)
Expand Down
8 changes: 7 additions & 1 deletion lib/bcdd/result/expectations/mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,13 @@ module Continue
end
end

OPTIONS = { continue: Continue }.freeze
module Given
private def Given(value)
Success.new(type: :given, value: value, subject: self)
end
end

OPTIONS = { continue: Continue, given: Given }.freeze

def self.options(config_flags)
Config::Options.addon(map: config_flags, from: OPTIONS)
Expand Down
8 changes: 7 additions & 1 deletion lib/bcdd/result/mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ def Success(type, value = nil)
end
end

OPTIONS = { continue: Continue }.freeze
module Given
private def Given(value)
_ResultAs(Success, :given, value)
end
end

OPTIONS = { continue: Continue, given: Given }.freeze

def self.options(config_flags)
Config::Options.addon(map: config_flags, from: OPTIONS)
Expand Down
1 change: 1 addition & 0 deletions sig/bcdd/result/config.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class BCDD::Result::Config::Switcher
end

module BCDD::Result::Config::Addons
AFFECTS: Array[String]
OPTIONS: Hash[String, Hash[Symbol, untyped]]

def self.switcher: -> BCDD::Result::Config::Switcher
Expand Down
12 changes: 12 additions & 0 deletions sig/bcdd/result/context.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ class BCDD::Result::Context
def Continue: (**untyped) -> BCDD::Result::Context::Success
end

module Given
include BCDD::Result::Context::Mixin::Methods

private

def Given: (*untyped) -> BCDD::Result::Context::Success
end

OPTIONS: Hash[Symbol, Module]

def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
Expand Down Expand Up @@ -95,6 +103,10 @@ module BCDD::Result::Context::Expectations::Mixin
private def Continue: (**untyped) -> BCDD::Result::Context::Success
end

module Given
private def Given: (*untyped) -> BCDD::Result::Context::Success
end

OPTIONS: Hash[Symbol, Module]

def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
Expand Down
4 changes: 4 additions & 0 deletions sig/bcdd/result/expectations.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ module BCDD::Result::Expectations::Mixin
private def Continue: (untyped) -> BCDD::Result::Success
end

module Given
private def Given: (untyped) -> BCDD::Result::Success
end

OPTIONS: Hash[Symbol, Module]

def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
Expand Down
8 changes: 8 additions & 0 deletions sig/bcdd/result/mixin.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ class BCDD::Result
def Continue: (untyped) -> BCDD::Result::Success
end

module Given
include BCDD::Result::Mixin::Methods

private

def Given: (untyped) -> BCDD::Result::Success
end

OPTIONS: Hash[Symbol, Module]

def self.options: (Hash[Symbol, Hash[Symbol, bool]]) -> Hash[Symbol, Module]
Expand Down
119 changes: 119 additions & 0 deletions test/bcdd/result/addons/given/expectations_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# frozen_string_literal: true

require 'test_helper'

class BCDD::Result::AddonsGivenExpectationsTest < Minitest::Test
class DivideType
include BCDD::Result::Expectations.mixin(
config: { addon: { continue: true } },
success: :ok,
failure: :err
)

def call(arg1, arg2)
Given([arg1, arg2])
.and_then(:validate_numbers)
.and_then(:validate_non_zero)
.and_then(:divide)
end

private

def validate_numbers(numbers)
number1, number2 = numbers

number1.is_a?(::Numeric) or return Failure(:err, 'arg1 must be numeric')
number2.is_a?(::Numeric) or return Failure(:err, 'arg2 must be numeric')

Continue(numbers)
end

def validate_non_zero(numbers)
return Continue(numbers) unless numbers.last.zero?

Failure(:err, 'arg2 must not be zero')
end

def divide((number1, number2))
Success(:ok, number1 / number2)
end
end

class DivideTypes
include BCDD::Result::Expectations.mixin(
config: { addon: { continue: true } },
success: :division_completed,
failure: %i[invalid_arg division_by_zero]
)

def call(arg1, arg2)
Given([arg1, arg2])
.and_then(:validate_numbers)
.and_then(:validate_non_zero)
.and_then(:divide)
end

private

def validate_numbers((arg1, arg2))
arg1.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg1 must be numeric')
arg2.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg2 must be numeric')

Continue([arg1, arg2])
end

def validate_non_zero(numbers)
return Continue(numbers) unless numbers.last.zero?

Failure(:division_by_zero, 'arg2 must not be zero')
end

def divide((number1, number2))
Success(:division_completed, number1 / number2)
end
end

module DivideTypeAndValue
extend self, BCDD::Result::Expectations.mixin(
config: { addon: { continue: true } },
success: { division_completed: Numeric },
failure: { invalid_arg: String, division_by_zero: String }
)

def call(arg1, arg2)
Given([arg1, arg2])
.and_then(:validate_numbers)
.and_then(:validate_non_zero)
.and_then(:divide)
end

private

def validate_numbers((arg1, arg2))
arg1.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg1 must be numeric')
arg2.is_a?(::Numeric) or return Failure(:invalid_arg, 'arg2 must be numeric')

Continue([arg1, arg2])
end

def validate_non_zero(numbers)
return Continue(numbers) unless numbers.last.zero?

Failure(:division_by_zero, 'arg2 must not be zero')
end

def divide((number1, number2))
Success(:division_completed, number1 / number2)
end
end

test 'method chaining' do
result1 = DivideType.new.call(10, 2)
result2 = DivideTypes.new.call(10, 2)
result3 = DivideTypeAndValue.call(10, 2)

assert result1.success?(:ok)
assert result2.success?(:division_completed)
assert result3.success?(:division_completed)
end
end
59 changes: 59 additions & 0 deletions test/bcdd/result/addons/given/instance_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# frozen_string_literal: true

require 'test_helper'

class BCDD::Result::AddonsGivenInstanceTest < Minitest::Test
class Divide
include BCDD::Result.mixin(config: { addon: { continue: true } })

def call(arg1, arg2)
Given([arg1, arg2])
.and_then(:validate_numbers)
.and_then(:validate_non_zero)
.and_then(:divide)
end

private

def validate_numbers((arg1, arg2))
arg1.is_a?(Numeric) or return Failure(:invalid_arg, 'arg1 must be numeric')
arg2.is_a?(Numeric) or return Failure(:invalid_arg, 'arg2 must be numeric')

Continue([arg1, arg2])
end

def validate_non_zero(numbers)
return Continue(numbers) unless numbers.last.zero?

Failure(:division_by_zero, 'arg2 must not be zero')
end

def divide((number1, number2))
Success(:division_completed, number1 / number2)
end
end

test 'method chaining' do
success = Divide.new.call(10, 2)

failure1 = Divide.new.call('10', 0)
failure2 = Divide.new.call(10, '2')
failure3 = Divide.new.call(10, 0)

assert_predicate success, :success?
assert_equal :division_completed, success.type
assert_equal 5, success.value

assert_predicate failure1, :failure?
assert_equal :invalid_arg, failure1.type
assert_equal 'arg1 must be numeric', failure1.value

assert_predicate failure2, :failure?
assert_equal :invalid_arg, failure2.type
assert_equal 'arg2 must be numeric', failure2.value

assert_predicate failure3, :failure?
assert_equal :division_by_zero, failure3.type
assert_equal 'arg2 must not be zero', failure3.value
end
end
59 changes: 59 additions & 0 deletions test/bcdd/result/addons/given/singleton_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# frozen_string_literal: true

require 'test_helper'

class BCDD::Result::AddonsGivenSingletonTest < Minitest::Test
module Divide
extend self, BCDD::Result.mixin(config: { addon: { continue: true } })

def call(arg1, arg2)
Given([arg1, arg2])
.and_then(:validate_numbers)
.and_then(:validate_non_zero)
.and_then(:divide)
end

private

def validate_numbers((arg1, arg2))
arg1.is_a?(Numeric) or return Failure(:invalid_arg, 'arg1 must be numeric')
arg2.is_a?(Numeric) or return Failure(:invalid_arg, 'arg2 must be numeric')

Continue([arg1, arg2])
end

def validate_non_zero(numbers)
return Continue(numbers) unless numbers.last.zero?

Failure(:division_by_zero, 'arg2 must not be zero')
end

def divide((number1, number2))
Success(:division_completed, number1 / number2)
end
end

test 'method chaining using Continue' do
success = Divide.call(10, 2)

failure1 = Divide.call('10', 0)
failure2 = Divide.call(10, '2')
failure3 = Divide.call(10, 0)

assert_predicate success, :success?
assert_equal :division_completed, success.type
assert_equal 5, success.value

assert_predicate failure1, :failure?
assert_equal :invalid_arg, failure1.type
assert_equal 'arg1 must be numeric', failure1.value

assert_predicate failure2, :failure?
assert_equal :invalid_arg, failure2.type
assert_equal 'arg2 must be numeric', failure2.value

assert_predicate failure3, :failure?
assert_equal :division_by_zero, failure3.type
assert_equal 'arg2 must not be zero', failure3.value
end
end
Loading

0 comments on commit 57c6888

Please sign in to comment.