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,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Fear::Either::Mixin do
|
4
|
+
include Fear::Either::Mixin
|
5
|
+
|
6
|
+
describe "Left()" do
|
7
|
+
subject { Left(42) }
|
8
|
+
|
9
|
+
it { is_expected.to eq(Fear::Left.new(42)) }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "Right()" do
|
13
|
+
subject { Right(42) }
|
14
|
+
|
15
|
+
it { is_expected.to eq(Fear::Right.new(42)) }
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Fear::EitherPatternMatch do
|
4
|
+
context "Right" do
|
5
|
+
let(:matcher) do
|
6
|
+
described_class.new do |m|
|
7
|
+
m.right(:even?.to_proc) { |x| "#{x} is even" }
|
8
|
+
m.right(:odd?.to_proc) { |x| "#{x} is odd" }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it do
|
13
|
+
expect(matcher.(Fear.right(4))).to eq("4 is even")
|
14
|
+
expect(matcher.(Fear.right(3))).to eq("3 is odd")
|
15
|
+
expect do
|
16
|
+
matcher.(Fear.left(44))
|
17
|
+
end.to raise_error(Fear::MatchError)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "Left" do
|
22
|
+
let(:matcher) do
|
23
|
+
described_class.new do |m|
|
24
|
+
m.left(:even?.to_proc) { |x| "#{x} is even" }
|
25
|
+
m.left(:odd?.to_proc) { |x| "#{x} is odd" }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it do
|
30
|
+
expect(matcher.(Fear.left(4))).to eq("4 is even")
|
31
|
+
expect(matcher.(Fear.left(3))).to eq("3 is odd")
|
32
|
+
expect do
|
33
|
+
matcher.(Fear.right(44))
|
34
|
+
end.to raise_error(Fear::MatchError)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Fear::Either do
|
4
|
+
describe "pattern matching" do
|
5
|
+
subject do
|
6
|
+
case value
|
7
|
+
in Fear::Right[Integer => int]
|
8
|
+
"right of #{int}"
|
9
|
+
in Fear::Left[Integer => int]
|
10
|
+
"left of #{int}"
|
11
|
+
else
|
12
|
+
"something else"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when value is right of integer" do
|
17
|
+
let(:value) { Fear.right(42) }
|
18
|
+
|
19
|
+
it { is_expected.to eq("right of 42") }
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when value is left of integer" do
|
23
|
+
let(:value) { Fear.left(42) }
|
24
|
+
|
25
|
+
it { is_expected.to eq("left of 42") }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Fear::Extractor::ArrayMatcher do
|
4
|
+
let(:parser) { Fear::Extractor::GrammarParser.new }
|
5
|
+
let(:matcher) { parser.parse(pattern).to_matcher }
|
6
|
+
|
7
|
+
describe "#defined_at?" do
|
8
|
+
subject { matcher }
|
9
|
+
|
10
|
+
context "empty array" do
|
11
|
+
let(:pattern) { "[]" }
|
12
|
+
|
13
|
+
it { is_expected.to be_defined_at([]) }
|
14
|
+
it { is_expected.not_to be_defined_at([1]) }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "empty array with splat" do
|
18
|
+
let(:pattern) { "[*]" }
|
19
|
+
|
20
|
+
it { is_expected.to be_defined_at([]) }
|
21
|
+
it { is_expected.to be_defined_at([1]) }
|
22
|
+
it { is_expected.to be_defined_at([1, 2]) }
|
23
|
+
end
|
24
|
+
|
25
|
+
context "empty array with named splat" do
|
26
|
+
let(:pattern) { "[*var]" }
|
27
|
+
|
28
|
+
it { is_expected.to be_defined_at([]) }
|
29
|
+
it { is_expected.to be_defined_at([1]) }
|
30
|
+
it { is_expected.to be_defined_at([1, 2]) }
|
31
|
+
end
|
32
|
+
|
33
|
+
context "one element array" do
|
34
|
+
let(:pattern) { "[1]" }
|
35
|
+
|
36
|
+
it { is_expected.not_to be_defined_at([]) }
|
37
|
+
it { is_expected.to be_defined_at([1]) }
|
38
|
+
it { is_expected.not_to be_defined_at([1, 2]) }
|
39
|
+
it { is_expected.not_to be_defined_at([2, 1]) }
|
40
|
+
|
41
|
+
context "identifier" do
|
42
|
+
let(:pattern) { "[var]" }
|
43
|
+
|
44
|
+
it { is_expected.not_to be_defined_at([]) }
|
45
|
+
it { is_expected.to be_defined_at([1]) }
|
46
|
+
it { is_expected.to be_defined_at([[1]]) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "two elements array with nested matcher" do
|
51
|
+
let(:pattern) { "[[1, *], 1]" }
|
52
|
+
|
53
|
+
it { is_expected.not_to be_defined_at([]) }
|
54
|
+
it { is_expected.to be_defined_at([[1], 1]) }
|
55
|
+
it { is_expected.to be_defined_at([[1, 2], 1]) }
|
56
|
+
it { is_expected.not_to be_defined_at([[1, 2], 2]) }
|
57
|
+
it { is_expected.not_to be_defined_at([2, 1]) }
|
58
|
+
end
|
59
|
+
|
60
|
+
context "one element array with splat" do
|
61
|
+
let(:pattern) { "[1, *]" }
|
62
|
+
|
63
|
+
it { is_expected.not_to be_defined_at([]) }
|
64
|
+
it { is_expected.to be_defined_at([1]) }
|
65
|
+
it { is_expected.to be_defined_at([1, 2]) }
|
66
|
+
it { is_expected.to be_defined_at([1, 2, 3]) }
|
67
|
+
it { is_expected.not_to be_defined_at([2, 1]) }
|
68
|
+
end
|
69
|
+
|
70
|
+
context "one element array with named splat" do
|
71
|
+
let(:pattern) { "[1, *var]" }
|
72
|
+
|
73
|
+
it { is_expected.not_to be_defined_at([]) }
|
74
|
+
it { is_expected.to be_defined_at([1]) }
|
75
|
+
it { is_expected.to be_defined_at([1, 2]) }
|
76
|
+
it { is_expected.to be_defined_at([1, 2, 3]) }
|
77
|
+
it { is_expected.not_to be_defined_at([2, 1]) }
|
78
|
+
end
|
79
|
+
|
80
|
+
context "three elements array" do
|
81
|
+
context "with identifier in the middle" do
|
82
|
+
let(:pattern) { "[1, var, 2]" }
|
83
|
+
|
84
|
+
it { is_expected.not_to be_defined_at([]) }
|
85
|
+
it { is_expected.to be_defined_at([1, 3, 2]) }
|
86
|
+
it { is_expected.not_to be_defined_at([1, 2, 3]) }
|
87
|
+
it { is_expected.not_to be_defined_at([1, 2, 3, 4]) }
|
88
|
+
it { is_expected.not_to be_defined_at([1]) }
|
89
|
+
it { is_expected.not_to be_defined_at([2]) }
|
90
|
+
end
|
91
|
+
|
92
|
+
context "head and tail" do
|
93
|
+
let(:pattern) { "[head, *tail]" }
|
94
|
+
|
95
|
+
it { is_expected.not_to be_defined_at([]) }
|
96
|
+
it { is_expected.to be_defined_at([1, 3, 2]) }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "two element array" do
|
101
|
+
let(:pattern) { "[ 1, 2 ]" }
|
102
|
+
|
103
|
+
it { is_expected.not_to be_defined_at([]) }
|
104
|
+
it { is_expected.to be_defined_at([1, 2]) }
|
105
|
+
it { is_expected.not_to be_defined_at([1]) }
|
106
|
+
it { is_expected.not_to be_defined_at([2]) }
|
107
|
+
it { is_expected.not_to be_defined_at([1, 3]) }
|
108
|
+
it { is_expected.not_to be_defined_at([2, 2]) }
|
109
|
+
it { is_expected.not_to be_defined_at([1, 2, 3]) }
|
110
|
+
|
111
|
+
context "with identifier at the beginning" do
|
112
|
+
let(:pattern) { "[var, 2]" }
|
113
|
+
|
114
|
+
it { is_expected.not_to be_defined_at([]) }
|
115
|
+
it { is_expected.to be_defined_at([1, 2]) }
|
116
|
+
it { is_expected.not_to be_defined_at([1, 3]) }
|
117
|
+
it { is_expected.not_to be_defined_at([1]) }
|
118
|
+
it { is_expected.not_to be_defined_at([2]) }
|
119
|
+
it { is_expected.not_to be_defined_at([1, 2, 3]) }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "#call" do
|
125
|
+
subject { matcher.(other) }
|
126
|
+
|
127
|
+
context "on the same array" do
|
128
|
+
let(:other) { [1] }
|
129
|
+
let(:pattern) { "[1]" }
|
130
|
+
|
131
|
+
it { is_expected.to eq({}) }
|
132
|
+
end
|
133
|
+
|
134
|
+
context "with splat on another array" do
|
135
|
+
let(:other) { [2, 1] }
|
136
|
+
let(:pattern) { "[2, *]" }
|
137
|
+
|
138
|
+
it { is_expected.to eq({}) }
|
139
|
+
end
|
140
|
+
|
141
|
+
context "with identifier at the middle of an array" do
|
142
|
+
let(:other) { [2, 1, 3] }
|
143
|
+
let(:pattern) { "[2, var, 3]" }
|
144
|
+
|
145
|
+
it { is_expected.to eq(var: 1) }
|
146
|
+
end
|
147
|
+
|
148
|
+
context "with identifier at the end of an array" do
|
149
|
+
let(:other) { [2, 1, 3] }
|
150
|
+
let(:pattern) { "[2, 1, var]" }
|
151
|
+
|
152
|
+
it { is_expected.to eq(var: 3) }
|
153
|
+
end
|
154
|
+
|
155
|
+
context "with named splat matching all the array" do
|
156
|
+
let(:other) { [2, 1, 3, 4] }
|
157
|
+
let(:pattern) { "[*var]" }
|
158
|
+
|
159
|
+
it { is_expected.to eq(var: [2, 1, 3, 4]) }
|
160
|
+
end
|
161
|
+
|
162
|
+
context "with named splat matching tail of an array" do
|
163
|
+
let(:other) { [2, 1, 3, 4] }
|
164
|
+
let(:pattern) { "[2, 1, *var]" }
|
165
|
+
|
166
|
+
it { is_expected.to eq(var: [3, 4]) }
|
167
|
+
end
|
168
|
+
|
169
|
+
context "with named splat at the end of an array" do
|
170
|
+
let(:other) { [2, 1] }
|
171
|
+
let(:pattern) { "[2, 1, *var]" }
|
172
|
+
|
173
|
+
it { is_expected.to eq(var: []) }
|
174
|
+
end
|
175
|
+
|
176
|
+
context "with several identifiers in an array" do
|
177
|
+
let(:other) { [2, 1, 3] }
|
178
|
+
let(:pattern) { "[a, 1, b]" }
|
179
|
+
|
180
|
+
it { is_expected.to eq(a: 2, b: 3) }
|
181
|
+
end
|
182
|
+
|
183
|
+
context "head and tail" do
|
184
|
+
let(:other) { [2, 1, 3] }
|
185
|
+
let(:pattern) { "[head, *tail]" }
|
186
|
+
|
187
|
+
it { is_expected.to eq(head: 2, tail: [1, 3]) }
|
188
|
+
end
|
189
|
+
|
190
|
+
context "ignore head, capture tail" do
|
191
|
+
let(:other) { [2, 1, 3] }
|
192
|
+
let(:pattern) { "[_, *tail]" }
|
193
|
+
|
194
|
+
it { is_expected.to eq(tail: [1, 3]) }
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
describe "#failure_reason" do
|
199
|
+
subject { matcher.failure_reason(other) }
|
200
|
+
|
201
|
+
context "on the same array" do
|
202
|
+
let(:other) { [1] }
|
203
|
+
let(:pattern) { "[1]" }
|
204
|
+
|
205
|
+
it { is_expected.to eq(Fear.none) }
|
206
|
+
end
|
207
|
+
|
208
|
+
context "on another array" do
|
209
|
+
let(:other) { [2, 1] }
|
210
|
+
let(:pattern) { "[2, 2]" }
|
211
|
+
|
212
|
+
it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
|
213
|
+
Expected `1` to match:
|
214
|
+
[2, 2]
|
215
|
+
~~~~^
|
216
|
+
ERROR
|
217
|
+
end
|
218
|
+
|
219
|
+
context "element type mismatch" do
|
220
|
+
let(:other) { [2, 1] }
|
221
|
+
let(:pattern) { "[[2], 1]" }
|
222
|
+
|
223
|
+
it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
|
224
|
+
Expected `2` to match:
|
225
|
+
[[2], 1]
|
226
|
+
~~^
|
227
|
+
ERROR
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Fear::Extractor::ExtractorMatcher do
|
4
|
+
let(:parser) { Fear::Extractor::GrammarParser.new }
|
5
|
+
let(:matcher) { parser.parse(pattern).to_matcher }
|
6
|
+
|
7
|
+
describe "#defined_at?" do
|
8
|
+
subject { matcher }
|
9
|
+
|
10
|
+
context "boolean extractor" do
|
11
|
+
let(:pattern) { "IsEven()" }
|
12
|
+
|
13
|
+
it { is_expected.to be_defined_at(42) }
|
14
|
+
it { is_expected.not_to be_defined_at(43) }
|
15
|
+
it { is_expected.not_to be_defined_at("foo") }
|
16
|
+
end
|
17
|
+
|
18
|
+
context "single argument extractor" do
|
19
|
+
let(:pattern) { "Fear::Some(a : Integer)" }
|
20
|
+
|
21
|
+
it { is_expected.to be_defined_at(Fear.some(42)) }
|
22
|
+
it { is_expected.not_to be_defined_at("foo") }
|
23
|
+
it { is_expected.not_to be_defined_at(Fear.some("foo")) }
|
24
|
+
end
|
25
|
+
|
26
|
+
context "single argument extractor with array as an argument" do
|
27
|
+
let(:pattern) { "Fear::Some([1, 2])" }
|
28
|
+
|
29
|
+
it { is_expected.to be_defined_at(Fear.some([1, 2])) }
|
30
|
+
it { is_expected.not_to be_defined_at(Fear.some([1, 1])) }
|
31
|
+
it { is_expected.not_to be_defined_at(Fear.some("foo")) }
|
32
|
+
end
|
33
|
+
|
34
|
+
context "multiple arguments extractor" do
|
35
|
+
let(:pattern) { "Date(2017, month, _)" }
|
36
|
+
|
37
|
+
it { is_expected.to be_defined_at(Date.parse("2017-02-15")) }
|
38
|
+
it { is_expected.not_to be_defined_at(Date.parse("2018-02-15")) }
|
39
|
+
it { is_expected.not_to be_defined_at("foo") }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "Struct" do
|
43
|
+
StructDate = ::Struct.new(:year, :month, :day)
|
44
|
+
|
45
|
+
let(:pattern) { "StructDate(2017, month, _)" }
|
46
|
+
|
47
|
+
it { is_expected.to be_defined_at(StructDate.new(2017, 2, 15)) }
|
48
|
+
it { is_expected.not_to be_defined_at(StructDate.new(2018, 2, 15)) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#call" do
|
53
|
+
subject { matcher.(other) }
|
54
|
+
|
55
|
+
context "single argument extractor" do
|
56
|
+
let(:pattern) { "Fear::Some(a : Integer)" }
|
57
|
+
let(:other) { Fear.some(42) }
|
58
|
+
|
59
|
+
it { is_expected.to eq(a: 42) }
|
60
|
+
end
|
61
|
+
|
62
|
+
context "multiple arguments extractor" do
|
63
|
+
let(:pattern) { "Date(2017, month, day)" }
|
64
|
+
let(:other) { Date.parse("2017-02-15") }
|
65
|
+
|
66
|
+
it { is_expected.to eq(month: 2, day: 15) }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#failure_reason" do
|
71
|
+
subject { matcher.failure_reason(other) }
|
72
|
+
|
73
|
+
context "no argument extractor" do
|
74
|
+
let(:pattern) { "IsEven()" }
|
75
|
+
|
76
|
+
context "defined" do
|
77
|
+
let(:other) { 42 }
|
78
|
+
|
79
|
+
it { is_expected.to eq(Fear.none) }
|
80
|
+
end
|
81
|
+
|
82
|
+
context "not defined" do
|
83
|
+
let(:other) { 43 }
|
84
|
+
|
85
|
+
it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
|
86
|
+
Expected `43` to match:
|
87
|
+
IsEven()
|
88
|
+
^
|
89
|
+
MSG
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "single argument extractor" do
|
94
|
+
let(:pattern) { "Fear::Some(a : Integer)" }
|
95
|
+
|
96
|
+
context "defined" do
|
97
|
+
let(:other) { Fear.some(42) }
|
98
|
+
|
99
|
+
it { is_expected.to eq(Fear.none) }
|
100
|
+
end
|
101
|
+
|
102
|
+
context "not defined" do
|
103
|
+
let(:other) { Fear.some("42") }
|
104
|
+
|
105
|
+
it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
|
106
|
+
Expected `"42"` to match:
|
107
|
+
Fear::Some(a : Integer)
|
108
|
+
~~~~~~~~~~~~~~~^
|
109
|
+
MSG
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "single argument extractor, array argument" do
|
114
|
+
let(:pattern) { "Fear::Some([1, 2])" }
|
115
|
+
|
116
|
+
context "defined" do
|
117
|
+
let(:other) { Fear.some([1, 2]) }
|
118
|
+
|
119
|
+
it { is_expected.to eq(Fear.none) }
|
120
|
+
end
|
121
|
+
|
122
|
+
context "not defined" do
|
123
|
+
let(:other) { Fear.some([1, 1]) }
|
124
|
+
|
125
|
+
it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
|
126
|
+
Expected `1` to match:
|
127
|
+
Fear::Some([1, 2])
|
128
|
+
~~~~~~~~~~~~~~~^
|
129
|
+
MSG
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "multiple arguments extractor" do
|
134
|
+
let(:pattern) { "Date(year, 02, day)" }
|
135
|
+
|
136
|
+
context "defined" do
|
137
|
+
let(:other) { Date.parse("2017-02-15") }
|
138
|
+
|
139
|
+
it { is_expected.to eq(Fear.none) }
|
140
|
+
end
|
141
|
+
|
142
|
+
context "not defined" do
|
143
|
+
let(:other) { Date.parse("2017-04-15") }
|
144
|
+
|
145
|
+
it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
|
146
|
+
Expected `4` to match:
|
147
|
+
Date(year, 02, day)
|
148
|
+
~~~~~~~~~~~^
|
149
|
+
MSG
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|