fear 0.9.0 → 1.2.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 +5 -5
- data/.github/workflows/rubocop.yml +39 -0
- data/.github/workflows/spec.yml +42 -0
- data/.gitignore +0 -1
- data/.rubocop.yml +4 -12
- data/.simplecov +17 -0
- data/CHANGELOG.md +40 -0
- data/Gemfile +5 -2
- data/Gemfile.lock +130 -0
- data/LICENSE.txt +1 -1
- data/README.md +1293 -97
- data/Rakefile +369 -1
- data/benchmarks/README.md +1 -0
- data/benchmarks/dry_do_vs_fear_for.txt +11 -0
- data/benchmarks/dry_some_fmap_vs_fear_some_map.txt +11 -0
- data/benchmarks/factorial.txt +16 -0
- data/benchmarks/fear_gaurd_and1_vs_new.txt +13 -0
- data/benchmarks/fear_gaurd_and2_vs_and.txt +13 -0
- data/benchmarks/fear_gaurd_and3_vs_and_and.txt +13 -0
- data/benchmarks/fear_pattern_extracting_with_vs_without_cache.txt +11 -0
- data/benchmarks/fear_pattern_matching_construction_vs_execution.txt +13 -0
- data/benchmarks/pattern_matching_dry_vs_qo_vs_fear_try.txt +14 -0
- data/benchmarks/pattern_matching_qo_vs_fear_pattern_extraction.txt +11 -0
- data/benchmarks/pattern_matching_qo_vs_fear_try_execution.txt +11 -0
- data/examples/pattern_extracting.rb +17 -0
- data/examples/pattern_extracting_ruby2.7.rb +15 -0
- data/examples/pattern_matching_binary_tree_set.rb +101 -0
- data/examples/pattern_matching_number_in_words.rb +60 -0
- data/fear.gemspec +34 -23
- data/lib/dry/types/fear.rb +8 -0
- data/lib/dry/types/fear/option.rb +125 -0
- data/lib/fear.rb +65 -15
- data/lib/fear/await.rb +33 -0
- data/lib/fear/awaitable.rb +28 -0
- data/lib/fear/either.rb +131 -71
- data/lib/fear/either_api.rb +23 -0
- data/lib/fear/either_pattern_match.rb +53 -0
- data/lib/fear/empty_partial_function.rb +38 -0
- data/lib/fear/extractor.rb +112 -0
- data/lib/fear/extractor/anonymous_array_splat_matcher.rb +10 -0
- data/lib/fear/extractor/any_matcher.rb +17 -0
- data/lib/fear/extractor/array_head_matcher.rb +36 -0
- data/lib/fear/extractor/array_matcher.rb +40 -0
- data/lib/fear/extractor/array_splat_matcher.rb +16 -0
- data/lib/fear/extractor/empty_list_matcher.rb +20 -0
- data/lib/fear/extractor/extractor_matcher.rb +44 -0
- data/lib/fear/extractor/grammar.rb +203 -0
- data/lib/fear/extractor/grammar.treetop +129 -0
- data/lib/fear/extractor/identifier_matcher.rb +18 -0
- data/lib/fear/extractor/matcher.rb +53 -0
- data/lib/fear/extractor/matcher/and.rb +38 -0
- data/lib/fear/extractor/named_array_splat_matcher.rb +17 -0
- data/lib/fear/extractor/pattern.rb +58 -0
- data/lib/fear/extractor/typed_identifier_matcher.rb +26 -0
- data/lib/fear/extractor/value_matcher.rb +19 -0
- data/lib/fear/extractor_api.rb +35 -0
- data/lib/fear/failure.rb +46 -14
- data/lib/fear/failure_pattern_match.rb +10 -0
- data/lib/fear/for.rb +37 -95
- data/lib/fear/for_api.rb +68 -0
- data/lib/fear/future.rb +497 -0
- data/lib/fear/future_api.rb +21 -0
- data/lib/fear/left.rb +19 -2
- data/lib/fear/left_pattern_match.rb +11 -0
- data/lib/fear/none.rb +67 -3
- data/lib/fear/none_pattern_match.rb +14 -0
- data/lib/fear/option.rb +120 -56
- data/lib/fear/option_api.rb +40 -0
- data/lib/fear/option_pattern_match.rb +48 -0
- data/lib/fear/partial_function.rb +176 -0
- data/lib/fear/partial_function/and_then.rb +50 -0
- data/lib/fear/partial_function/any.rb +28 -0
- data/lib/fear/partial_function/combined.rb +53 -0
- data/lib/fear/partial_function/empty.rb +10 -0
- data/lib/fear/partial_function/guard.rb +80 -0
- data/lib/fear/partial_function/guard/and.rb +38 -0
- data/lib/fear/partial_function/guard/and3.rb +41 -0
- data/lib/fear/partial_function/guard/or.rb +38 -0
- data/lib/fear/partial_function/lifted.rb +23 -0
- data/lib/fear/partial_function/or_else.rb +64 -0
- data/lib/fear/partial_function_class.rb +38 -0
- data/lib/fear/pattern_match.rb +114 -0
- data/lib/fear/pattern_matching_api.rb +137 -0
- data/lib/fear/promise.rb +95 -0
- data/lib/fear/right.rb +20 -2
- data/lib/fear/right_biased.rb +6 -14
- data/lib/fear/right_pattern_match.rb +11 -0
- data/lib/fear/some.rb +55 -3
- data/lib/fear/some_pattern_match.rb +13 -0
- data/lib/fear/struct.rb +248 -0
- data/lib/fear/success.rb +35 -5
- data/lib/fear/success_pattern_match.rb +12 -0
- data/lib/fear/try.rb +136 -79
- data/lib/fear/try_api.rb +33 -0
- data/lib/fear/try_pattern_match.rb +33 -0
- data/lib/fear/unit.rb +32 -0
- data/lib/fear/utils.rb +39 -14
- data/lib/fear/version.rb +4 -1
- data/spec/dry/types/fear/option/constrained_spec.rb +22 -0
- data/spec/dry/types/fear/option/core_spec.rb +77 -0
- data/spec/dry/types/fear/option/default_spec.rb +21 -0
- data/spec/dry/types/fear/option/hash_spec.rb +58 -0
- data/spec/dry/types/fear/option/option_spec.rb +97 -0
- data/spec/fear/awaitable_spec.rb +17 -0
- data/spec/fear/done_spec.rb +8 -6
- data/spec/fear/either/mixin_spec.rb +17 -0
- data/spec/fear/either_pattern_match_spec.rb +37 -0
- data/spec/fear/either_pattern_matching_spec.rb +28 -0
- data/spec/fear/extractor/array_matcher_spec.rb +230 -0
- data/spec/fear/extractor/extractor_matcher_spec.rb +153 -0
- data/spec/fear/extractor/grammar_array_spec.rb +25 -0
- data/spec/fear/extractor/identified_matcher_spec.rb +49 -0
- data/spec/fear/extractor/identifier_matcher_spec.rb +68 -0
- data/spec/fear/extractor/pattern_spec.rb +34 -0
- data/spec/fear/extractor/typed_identifier_matcher_spec.rb +64 -0
- data/spec/fear/extractor/value_matcher_number_spec.rb +79 -0
- data/spec/fear/extractor/value_matcher_string_spec.rb +88 -0
- data/spec/fear/extractor/value_matcher_symbol_spec.rb +71 -0
- data/spec/fear/extractor_api_spec.rb +115 -0
- data/spec/fear/extractor_spec.rb +61 -0
- data/spec/fear/failure_spec.rb +145 -45
- data/spec/fear/for_spec.rb +57 -67
- data/spec/fear/future_spec.rb +691 -0
- data/spec/fear/guard_spec.rb +103 -0
- data/spec/fear/left_spec.rb +112 -46
- data/spec/fear/none_spec.rb +114 -16
- data/spec/fear/option/mixin_spec.rb +39 -0
- data/spec/fear/option_pattern_match_spec.rb +35 -0
- data/spec/fear/option_pattern_matching_spec.rb +34 -0
- data/spec/fear/option_spec.rb +121 -8
- data/spec/fear/partial_function/empty_spec.rb +38 -0
- data/spec/fear/partial_function_and_then_spec.rb +147 -0
- data/spec/fear/partial_function_composition_spec.rb +82 -0
- data/spec/fear/partial_function_or_else_spec.rb +276 -0
- data/spec/fear/partial_function_spec.rb +239 -0
- data/spec/fear/pattern_match_spec.rb +93 -0
- data/spec/fear/pattern_matching_api_spec.rb +31 -0
- data/spec/fear/promise_spec.rb +96 -0
- data/spec/fear/right_biased/left.rb +29 -32
- data/spec/fear/right_biased/right.rb +51 -54
- data/spec/fear/right_spec.rb +109 -41
- data/spec/fear/some_spec.rb +80 -15
- data/spec/fear/success_spec.rb +99 -32
- data/spec/fear/try/mixin_spec.rb +19 -0
- data/spec/fear/try_pattern_match_spec.rb +37 -0
- data/spec/fear/try_pattern_matching_spec.rb +34 -0
- data/spec/fear/utils_spec.rb +16 -14
- data/spec/spec_helper.rb +13 -7
- data/spec/struct_pattern_matching_spec.rb +36 -0
- data/spec/struct_spec.rb +226 -0
- data/spec/support/dry_types.rb +6 -0
- metadata +320 -29
- data/.travis.yml +0 -9
- data/lib/fear/done.rb +0 -22
- data/lib/fear/for/evaluation_context.rb +0 -91
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fear
|
4
|
+
# Try pattern matcher
|
5
|
+
#
|
6
|
+
# @note it has two optimized subclasses +Fear::SuccessPatternMatch+ and +Fear::FailurePatternMatch+
|
7
|
+
# @api private
|
8
|
+
class TryPatternMatch < Fear::PatternMatch
|
9
|
+
SUCCESS_EXTRACTOR = :get.to_proc
|
10
|
+
private_constant :SUCCESS_EXTRACTOR
|
11
|
+
|
12
|
+
FAILURE_EXTRACTOR = :exception.to_proc
|
13
|
+
private_constant :FAILURE_EXTRACTOR
|
14
|
+
|
15
|
+
# Match against +Fear::Success+
|
16
|
+
#
|
17
|
+
# @param conditions [<#==>]
|
18
|
+
# @return [Fear::TryPatternMatch]
|
19
|
+
def success(*conditions, &effect)
|
20
|
+
branch = Fear.case(Fear::Success, &SUCCESS_EXTRACTOR).and_then(Fear.case(*conditions, &effect))
|
21
|
+
or_else(branch)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Match against +Fear::Failure+
|
25
|
+
#
|
26
|
+
# @param conditions [<#==>]
|
27
|
+
# @return [Fear::TryPatternMatch]
|
28
|
+
def failure(*conditions, &effect)
|
29
|
+
branch = Fear.case(Fear::Failure, &FAILURE_EXTRACTOR).and_then(Fear.case(*conditions, &effect))
|
30
|
+
or_else(branch)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/fear/unit.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fear
|
4
|
+
# Represents lack of value. It's typically returned when function completed without a value.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# if user.valid?
|
8
|
+
# Fear.right(Fear::Unit)
|
9
|
+
# else
|
10
|
+
# Fear.left(user.errors)
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# def sent_notifications(user)
|
15
|
+
# # ...
|
16
|
+
# Fear::Unit
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
Unit = Object.new.tap do |unit|
|
20
|
+
# @return [String]
|
21
|
+
def unit.to_s
|
22
|
+
"#<Fear::Unit>"
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [String]
|
26
|
+
def unit.inspect
|
27
|
+
"#<Fear::Unit>"
|
28
|
+
end
|
29
|
+
end.freeze
|
30
|
+
|
31
|
+
public_constant :Unit
|
32
|
+
end
|
data/lib/fear/utils.rb
CHANGED
@@ -1,25 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Fear
|
2
4
|
# @private
|
3
5
|
module Utils
|
4
|
-
|
6
|
+
EMPTY_STRING = ""
|
7
|
+
public_constant :EMPTY_STRING
|
8
|
+
|
9
|
+
IDENTITY = :itself.to_proc
|
10
|
+
public_constant :IDENTITY
|
11
|
+
|
12
|
+
UNDEFINED = Object.new.freeze
|
13
|
+
public_constant :UNDEFINED
|
14
|
+
|
15
|
+
EMPTY_HASH = {}.freeze
|
16
|
+
public_constant :EMPTY_HASH
|
17
|
+
|
18
|
+
EMPTY_ARRAY = [].freeze
|
19
|
+
public_constant :EMPTY_ARRAY
|
5
20
|
|
6
|
-
|
7
|
-
|
8
|
-
|
21
|
+
class << self
|
22
|
+
def assert_arg_or_block!(method_name, *args)
|
23
|
+
unless block_given? ^ !args.empty?
|
24
|
+
raise ArgumentError, "##{method_name} accepts either one argument or block"
|
25
|
+
end
|
9
26
|
end
|
10
|
-
end
|
11
27
|
|
12
|
-
|
13
|
-
|
14
|
-
|
28
|
+
def with_block_or_argument(method_name, arg = UNDEFINED, block = nil)
|
29
|
+
if block.nil? ^ arg.equal?(UNDEFINED)
|
30
|
+
yield(block || arg)
|
31
|
+
else
|
32
|
+
raise ArgumentError, "#{method_name} accepts either block or partial function"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def assert_type!(value, *types)
|
37
|
+
if types.none? { |type| value.is_a?(type) }
|
38
|
+
raise TypeError, "expected `#{value.inspect}` to be of #{types.join(", ")} class"
|
39
|
+
end
|
15
40
|
end
|
16
|
-
end
|
17
41
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
42
|
+
def return_or_call_proc(value)
|
43
|
+
if value.respond_to?(:call)
|
44
|
+
value.()
|
45
|
+
else
|
46
|
+
value
|
47
|
+
end
|
23
48
|
end
|
24
49
|
end
|
25
50
|
end
|
data/lib/fear/version.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "support/dry_types"
|
4
|
+
|
5
|
+
RSpec.describe Dry::Types::Constrained, :option do
|
6
|
+
context "with a option type" do
|
7
|
+
subject(:type) do
|
8
|
+
Dry::Types["nominal.string"].constrained(size: 4).option
|
9
|
+
end
|
10
|
+
|
11
|
+
it_behaves_like "Dry::Types::Nominal without primitive"
|
12
|
+
|
13
|
+
it "passes when constraints are not violated" do
|
14
|
+
expect(type[nil]).to be_none
|
15
|
+
expect(type["hell"]).to be_some_of("hell")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "raises when a given constraint is violated" do
|
19
|
+
expect { type["hel"] }.to raise_error(Dry::Types::ConstraintError, /hel/)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "support/dry_types"
|
4
|
+
|
5
|
+
RSpec.describe Dry::Types::Nominal, :option do
|
6
|
+
describe "with opt-in option types" do
|
7
|
+
context "with strict string" do
|
8
|
+
let(:string) { Dry::Types["option.strict.string"] }
|
9
|
+
|
10
|
+
it_behaves_like "Dry::Types::Nominal without primitive" do
|
11
|
+
let(:type) { string }
|
12
|
+
end
|
13
|
+
|
14
|
+
it "accepts nil" do
|
15
|
+
expect(string[nil]).to be_none
|
16
|
+
end
|
17
|
+
|
18
|
+
it "accepts a string" do
|
19
|
+
expect(string["something"]).to be_some_of("something")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "with coercible string" do
|
24
|
+
let(:string) { Dry::Types["option.coercible.string"] }
|
25
|
+
|
26
|
+
it_behaves_like "Dry::Types::Nominal without primitive" do
|
27
|
+
let(:type) { string }
|
28
|
+
end
|
29
|
+
|
30
|
+
it "accepts nil" do
|
31
|
+
expect(string[nil]).to be_none
|
32
|
+
end
|
33
|
+
|
34
|
+
it "accepts a string" do
|
35
|
+
expect(string[:something]).to be_some_of("something")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "defining coercible Option String" do
|
41
|
+
let(:option_string) { Dry::Types["coercible.string"].option }
|
42
|
+
|
43
|
+
it_behaves_like "Dry::Types::Nominal without primitive" do
|
44
|
+
let(:type) { option_string }
|
45
|
+
end
|
46
|
+
|
47
|
+
it "accepts nil" do
|
48
|
+
expect(option_string[nil]).to be_none
|
49
|
+
end
|
50
|
+
|
51
|
+
it "accepts an object coercible to a string" do
|
52
|
+
expect(option_string[123]).to be_some_of("123")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "defining Option String" do
|
57
|
+
let(:option_string) { Dry::Types["strict.string"].option }
|
58
|
+
|
59
|
+
it_behaves_like "Dry::Types::Nominal without primitive" do
|
60
|
+
let(:type) { option_string }
|
61
|
+
end
|
62
|
+
|
63
|
+
it "accepts nil and returns None instance" do
|
64
|
+
value = option_string[nil]
|
65
|
+
|
66
|
+
expect(value).to be_none
|
67
|
+
expect(value.map(&:downcase).map(&:upcase)).to be_none
|
68
|
+
end
|
69
|
+
|
70
|
+
it "accepts a string and returns Some instance" do
|
71
|
+
value = option_string["SomeThing"]
|
72
|
+
|
73
|
+
expect(value).to be_some_of("SomeThing")
|
74
|
+
expect(value.map(&:downcase).map(&:upcase)).to be_some_of("SOMETHING")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "support/dry_types"
|
4
|
+
|
5
|
+
RSpec.describe Dry::Types::Nominal, "#default", :option do
|
6
|
+
context "with a maybe" do
|
7
|
+
subject(:type) { Dry::Types["strict.integer"].option }
|
8
|
+
|
9
|
+
it_behaves_like "Dry::Types::Nominal without primitive" do
|
10
|
+
let(:type) { Dry::Types["strict.integer"].option.default(0) }
|
11
|
+
end
|
12
|
+
|
13
|
+
it "does not allow nil" do
|
14
|
+
expect { type.default(nil) }.to raise_error(ArgumentError, /nil/)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "accepts a non-nil value" do
|
18
|
+
expect(type.default(0)[0]).to be_some_of(0)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "support/dry_types"
|
4
|
+
|
5
|
+
RSpec.describe Dry::Types::Hash, :option do
|
6
|
+
let(:email) { Dry::Types["option.strict.string"] }
|
7
|
+
|
8
|
+
context "Symbolized constructor" do
|
9
|
+
subject(:hash) do
|
10
|
+
Dry::Types["nominal.hash"].schema(
|
11
|
+
name: "string",
|
12
|
+
email: email,
|
13
|
+
).with_key_transform(&:to_sym)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#[]" do
|
17
|
+
it "sets None as a default value for option" do
|
18
|
+
result = hash["name" => "Jane"]
|
19
|
+
|
20
|
+
expect(result[:email]).to be_none
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "Schema constructor" do
|
26
|
+
subject(:hash) do
|
27
|
+
Dry::Types["nominal.hash"].schema(
|
28
|
+
name: "string",
|
29
|
+
email: email,
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#[]" do
|
34
|
+
it "sets None as a default value for option types" do
|
35
|
+
result = hash[name: "Jane"]
|
36
|
+
|
37
|
+
expect(result[:email]).to be_none
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "Strict with defaults" do
|
43
|
+
subject(:hash) do
|
44
|
+
Dry::Types["nominal.hash"].schema(
|
45
|
+
name: "string",
|
46
|
+
email: email,
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#[]" do
|
51
|
+
it "sets None as a default value for option types" do
|
52
|
+
result = hash[name: "Jane"]
|
53
|
+
|
54
|
+
expect(result[:email]).to be_none
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "support/dry_types"
|
4
|
+
|
5
|
+
RSpec.describe Dry::Types::Nominal, "#option", :option do
|
6
|
+
context "with a nominal" do
|
7
|
+
subject(:type) { Dry::Types["nominal.string"].option }
|
8
|
+
|
9
|
+
it_behaves_like "Dry::Types::Nominal without primitive"
|
10
|
+
|
11
|
+
it "returns None when value is nil" do
|
12
|
+
expect(type[nil]).to be_none
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns Some when value exists" do
|
16
|
+
expect(type["hello"]).to be_some_of("hello")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "returns original if input is already a option" do
|
20
|
+
expect(type[Fear.some("hello")]).to be_some_of("hello")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "aliases #[] as #call" do
|
24
|
+
expect(type.("hello")).to be_some_of("hello")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "does not have primitive" do
|
28
|
+
expect(type).to_not respond_to(:primitive)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "with a strict type" do
|
33
|
+
subject(:type) { Dry::Types["strict.integer"].option }
|
34
|
+
|
35
|
+
it_behaves_like "Dry::Types::Nominal without primitive"
|
36
|
+
|
37
|
+
it "returns None when value is nil" do
|
38
|
+
expect(type[nil]).to be_none
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns Some when value exists" do
|
42
|
+
expect(type[231]).to be_some_of(231)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "with a sum" do
|
47
|
+
subject(:type) { Dry::Types["nominal.bool"].option }
|
48
|
+
|
49
|
+
it_behaves_like "Dry::Types::Nominal without primitive"
|
50
|
+
|
51
|
+
it "returns None when value is nil" do
|
52
|
+
expect(type[nil]).to be_none
|
53
|
+
end
|
54
|
+
|
55
|
+
it "returns Some when value exists" do
|
56
|
+
expect(type[true]).to be_some_of(true)
|
57
|
+
expect(type[false]).to be_some_of(false)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "does not have primitive" do
|
61
|
+
expect(type).to_not respond_to(:primitive)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with keys" do
|
66
|
+
subject(:type) do
|
67
|
+
Dry::Types["hash"].schema(foo: Dry::Types["integer"]).key(:foo)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "gets wrapped by key type" do
|
71
|
+
expect(type.option).to be_a(Dry::Types::Schema::Key)
|
72
|
+
expect(type.option[nil]).to be_none
|
73
|
+
expect(type.option[1]).to be_some_of(1)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#try" do
|
78
|
+
subject(:type) { Dry::Types["coercible.integer"].option }
|
79
|
+
|
80
|
+
it "maps successful result" do
|
81
|
+
expect(type.try("1")).to eq(Dry::Types::Result::Success.new(Fear.some(1)))
|
82
|
+
expect(type.try(nil)).to eq(Dry::Types::Result::Success.new(Fear.none))
|
83
|
+
expect(type.try("a")).to be_a(Dry::Types::Result::Failure)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#call" do
|
88
|
+
describe "safe calls" do
|
89
|
+
subject(:type) { Dry::Types["coercible.integer"].option }
|
90
|
+
|
91
|
+
specify do
|
92
|
+
expect(type.("a") { :fallback }).to be(:fallback)
|
93
|
+
expect(type.(Fear.some(1)) { :fallback }).to eq(Fear.some(1))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Fear::Awaitable do
|
4
|
+
subject(:awaitable) { Object.new.extend(Fear::Awaitable) }
|
5
|
+
|
6
|
+
describe "#__ready__" do
|
7
|
+
it "must implement the method" do
|
8
|
+
expect { awaitable.__ready__(1) }.to raise_error(NotImplementedError)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#__result__" do
|
13
|
+
it "must implement the method" do
|
14
|
+
expect { awaitable.__result__(1) }.to raise_error(NotImplementedError)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/fear/done_spec.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Fear::Unit do
|
4
|
+
describe "#to_s" do
|
3
5
|
subject { described_class.to_s }
|
4
6
|
|
5
|
-
it { is_expected.to eq(
|
7
|
+
it { is_expected.to eq("#<Fear::Unit>") }
|
6
8
|
end
|
7
9
|
|
8
|
-
describe
|
10
|
+
describe "#inspect" do
|
9
11
|
subject { described_class.inspect }
|
10
12
|
|
11
|
-
it { is_expected.to eq(
|
13
|
+
it { is_expected.to eq("#<Fear::Unit>") }
|
12
14
|
end
|
13
15
|
|
14
|
-
describe
|
16
|
+
describe "#==" do
|
15
17
|
it { is_expected.to eq(described_class) }
|
16
18
|
end
|
17
19
|
end
|