much-result 0.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.
@@ -0,0 +1,57 @@
1
+ require "much-result"
2
+
3
+ class MuchResult; end
4
+ class MuchResult::Aggregate
5
+ def self.call(values)
6
+ new(values).call
7
+ end
8
+
9
+ def initialize(values)
10
+ @values = values
11
+ end
12
+
13
+ def call
14
+ combine_values(@values)
15
+ end
16
+
17
+ private
18
+
19
+ def combine_values(values)
20
+ combine_in_a_collection(array_wrap(values))
21
+ end
22
+
23
+ def combine_in_a_collection(values)
24
+ if all_hash_values?(values)
25
+ values.
26
+ reduce { |acc, value| combine_in_a_hash(acc, value) }.
27
+ transform_values { |nested_values| combine_values(nested_values) }
28
+ else
29
+ array_wrap(
30
+ values.reduce([]) { |acc, value| combine_in_an_array(acc, value) }
31
+ )
32
+ end
33
+ end
34
+
35
+ def combine_in_a_hash(hash1, hash2)
36
+ ((h1 = hash1 || {}).keys + (h2 = hash2 || {}).keys).
37
+ uniq.
38
+ reduce({}) { |hash, key|
39
+ hash[key] = combine_in_an_array(h1[key], h2[key])
40
+ hash
41
+ }
42
+ end
43
+
44
+ def combine_in_an_array(acc, other)
45
+ array_wrap(acc) + array_wrap(other)
46
+ end
47
+
48
+ def array_wrap(value)
49
+ value.kind_of?(Array) ? value : [value]
50
+ end
51
+
52
+ def all_hash_values?(values)
53
+ (compacted = values.compact).reduce(compacted.any?) { |acc, value|
54
+ acc && value.kind_of?(::Hash)
55
+ }
56
+ end
57
+ end
@@ -0,0 +1,56 @@
1
+ require "much-result"
2
+
3
+ class MuchResult; end
4
+ class MuchResult::Transaction
5
+ def self.halt_throw_value
6
+ :muchresult_transaction_halt
7
+ end
8
+
9
+ def self.call(receiver, **result_kargs, &block)
10
+ new(receiver, **result_kargs).call(&block)
11
+ end
12
+
13
+ def initialize(receiver, **result_kargs)
14
+ @receiver = receiver
15
+ @result_kargs = result_kargs
16
+
17
+ result.much_result_transaction_rolled_back = false
18
+ result.much_result_transaction_halted = false
19
+ end
20
+
21
+ def result
22
+ @result ||= MuchResult.success(**@result_kargs)
23
+ end
24
+
25
+ def call(&block)
26
+ begin
27
+ @receiver.transaction do
28
+ catch(self.class.halt_throw_value) { block.call(self) }
29
+ end
30
+ rescue MuchResult::Rollback
31
+ # do nothing
32
+ end
33
+
34
+ result
35
+ end
36
+
37
+ def rollback
38
+ result.much_result_transaction_rolled_back = true
39
+ raise MuchResult::Rollback
40
+ end
41
+
42
+ def halt
43
+ result.much_result_transaction_halted = true
44
+ throw(self.class.halt_throw_value)
45
+ end
46
+
47
+ private
48
+
49
+ def respond_to_missing?(*args)
50
+ result.send(:respond_to_missing?, *args)
51
+ end
52
+
53
+ def method_missing(method, *args, &block)
54
+ result.public_send(method, *args, &block)
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ class MuchResult
2
+ VERSION = "0.1.0"
3
+ end
File without changes
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "much-result/version"
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "much-result"
8
+ gem.version = MuchResult::VERSION
9
+ gem.authors = ["Kelly Redding", "Collin Redding"]
10
+ gem.email = ["kelly@kellyredding.com", "collin.redding@me.com"]
11
+ gem.summary = "API for managing the results of operations."
12
+ gem.description = "API for managing the results of operations."
13
+ gem.homepage = "https://github.com/redding/much-result"
14
+ gem.license = "MIT"
15
+
16
+ gem.files = `git ls-files | grep "^[^.]"`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.required_ruby_version = "~> 2.5"
22
+
23
+ gem.add_development_dependency("assert", ["~> 2.18.4"])
24
+ end
@@ -0,0 +1,10 @@
1
+ # this file is automatically required when you run `assert`
2
+ # put any test helpers here
3
+
4
+ # add the root dir to the load path
5
+ $LOAD_PATH.unshift(File.expand_path("../..", __FILE__))
6
+
7
+ # require pry for debugging (`binding.pry`)
8
+ require "pry"
9
+
10
+ require "test/support/factory"
@@ -0,0 +1,42 @@
1
+ require "assert/factory"
2
+ require "much-stub/call"
3
+
4
+ module Factory
5
+ extend Assert::Factory
6
+
7
+ def self.value
8
+ [Factory.integer, Factory.string, Object.new].sample
9
+ end
10
+
11
+ def self.hash_value(with_nested_hash = true)
12
+ {
13
+ value1: Factory.value,
14
+ value2: with_nested_hash ? Factory.hash_value(false) : Factory.value
15
+ }
16
+ end
17
+
18
+ def self.backtrace
19
+ Factory.integer(3).times.map{ Factory.path }
20
+ end
21
+
22
+ def self.transaction_receiver
23
+ FakeTransactionReceiver.new
24
+ end
25
+
26
+ class FakeTransactionReceiver
27
+ attr_reader :last_transaction_call
28
+
29
+ def transaction(&block)
30
+ @rolled_back = false
31
+ @last_transaction_call = MuchStub::Call.new(&block)
32
+ block.call
33
+ rescue => exception
34
+ @rolled_back = true
35
+ raise exception
36
+ end
37
+
38
+ def rolled_back?
39
+ !!@rolled_back
40
+ end
41
+ end
42
+ end
File without changes
@@ -0,0 +1,103 @@
1
+ require "assert"
2
+ require "much-result/aggregate"
3
+
4
+ class MuchResult::Aggregate
5
+ class UnitTests < Assert::Context
6
+ desc "MuchResult::Aggregate"
7
+ subject { unit_class }
8
+
9
+ let(:unit_class) { MuchResult::Aggregate }
10
+
11
+ let(:values1) {
12
+ [Factory.value, Factory.value, Factory.value, Hash.new]
13
+ }
14
+ let(:hash_values1) {
15
+ [Factory.hash_value, Factory.hash_value, Factory.hash_value]
16
+ }
17
+
18
+ should have_imeths :call
19
+
20
+ should "build instances and call them" do
21
+ Assert.stub_tap_on_call(subject, :new) { |instance, call|
22
+ @instance_new_call = call
23
+ Assert.stub(instance, :call) { @instance_called = true }
24
+ }
25
+
26
+ subject.call(values1)
27
+
28
+ assert_that(@instance_new_call.args).equals([values1])
29
+ assert_that(@instance_called).is_true
30
+ end
31
+ end
32
+
33
+ class InitTests < UnitTests
34
+ desc "when init"
35
+ subject { unit_class.new(init_values) }
36
+
37
+ let(:init_values) { [values1, hash_values1, [], nil].sample }
38
+
39
+ should have_imeths :call
40
+ end
41
+
42
+ class CalledWithAnEmptyArrayTests < InitTests
43
+ desc "and called with an empty Array"
44
+
45
+ let(:init_values) { [] }
46
+ # let(:init_values) { [[], nil, [nil, nil]].sample }
47
+
48
+ should "return an empty Array" do
49
+ assert_that(subject.call).equals([])
50
+ end
51
+ end
52
+
53
+ class CalledWithASingleNonHashValueTests < InitTests
54
+ desc "and called with single non-Hash value"
55
+
56
+ let(:init_values) { [Factory.value, nil].sample }
57
+
58
+ should "return the value wrapped in an Array" do
59
+ assert_that(subject.call).equals([init_values])
60
+ end
61
+ end
62
+
63
+ class CalledWithASingleHashValueTests < InitTests
64
+ desc "and called with single Hash value"
65
+
66
+ let(:value1) { [Factory.value, nil].sample }
67
+ let(:init_values) { { value: value1 } }
68
+
69
+ should "return the Hash with its values wrapped in an Array" do
70
+ assert_that(subject.call).equals(value: [value1])
71
+ end
72
+ end
73
+
74
+ class CalledWithAMixedValueArrayTests < InitTests
75
+ desc "and called with a mixed-value Array"
76
+
77
+ let(:init_values) { [nil, values1, [], { value: 1 }, nil] }
78
+
79
+ should "combines the values into an Array, flattening any sub-Arrays" do
80
+ assert_that(subject.call).equals([nil, *values1, { value: 1 }, nil])
81
+ end
82
+ end
83
+
84
+ class CalledWithAnAllHashValueArrayTests < InitTests
85
+ desc "and called with an all-Hash-value Array"
86
+
87
+ let(:init_values) { [nil] + hash_values1 + [nil] }
88
+
89
+ let(:expected_aggregate_value) {
90
+ {
91
+ value1: init_values.map { |hash| (hash || {})[:value1] },
92
+ value2: {
93
+ value1: init_values.map { |hash| (hash || {}).dig(:value2, :value1) },
94
+ value2: init_values.map { |hash| (hash || {}).dig(:value2, :value2) }
95
+ }
96
+ }
97
+ }
98
+
99
+ should "recursively combine the hash values, removing any nils" do
100
+ assert_that(subject.call).equals(expected_aggregate_value)
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,447 @@
1
+ require "assert"
2
+ require "much-result"
3
+
4
+ class MuchResult
5
+ class UnitTests < Assert::Context
6
+ desc "MuchResult"
7
+ subject { unit_class }
8
+
9
+ let(:unit_class) { MuchResult }
10
+
11
+ let(:identifier1) { Factory.string }
12
+ let(:description1) { Factory.string }
13
+ let(:backtrace1) { Factory.backtrace }
14
+ let(:value1) { Factory.value }
15
+
16
+ should have_imeths :success, :failure, :for, :tap, :transaction
17
+
18
+ should "build success instances" do
19
+ result = subject.success
20
+
21
+ assert_that(result.success?).is_true
22
+ assert_that(result.failure?).is_false
23
+
24
+ assert_that(result.sub_results).equals([])
25
+ assert_that(result.success_sub_results).equals([])
26
+ assert_that(result.failure_sub_results).equals([])
27
+
28
+ assert_that(result.all_results).equals([result])
29
+ assert_that(result.all_success_results).equals([result])
30
+ assert_that(result.all_failure_results).equals([])
31
+ end
32
+
33
+ should "build failure instances" do
34
+ result = subject.failure
35
+
36
+ assert_that(result.success?).is_false
37
+ assert_that(result.failure?).is_true
38
+
39
+ assert_that(result.sub_results).equals([])
40
+ assert_that(result.success_sub_results).equals([])
41
+ assert_that(result.failure_sub_results).equals([])
42
+
43
+ assert_that(result.all_results).equals([result])
44
+ assert_that(result.all_success_results).equals([])
45
+ assert_that(result.all_failure_results).equals([result])
46
+ end
47
+
48
+ should "build instances based on given values" do
49
+ true_result = subject.for(true, value: value1)
50
+ assert_that(true_result.success?).is_true
51
+ assert_that(true_result.failure?).is_false
52
+ assert_that(true_result.value).equals(value1)
53
+
54
+ false_result = subject.for(false, value: value1)
55
+ assert_that(false_result.success?).is_false
56
+ assert_that(false_result.failure?).is_true
57
+ assert_that(false_result.value).equals(value1)
58
+
59
+ value1_result = subject.for(value1, value: value1)
60
+ assert_that(value1_result.success?).is_true
61
+ assert_that(value1_result.failure?).is_false
62
+ assert_that(value1_result.value).equals(value1)
63
+
64
+ nil_result = subject.for(nil, value: value1)
65
+ assert_that(nil_result.success?).is_false
66
+ assert_that(nil_result.failure?).is_true
67
+ assert_that(nil_result.value).equals(value1)
68
+
69
+ result_result = subject.for(true_result, value2: value1)
70
+ assert_that(result_result).is_the_same_as(true_result)
71
+ assert_that(result_result.value2).equals(value1)
72
+ end
73
+
74
+ should "build instances yielded to a given block" do
75
+ yielded_result = nil
76
+ tap_result =
77
+ subject.tap { |result|
78
+ yielded_result = result
79
+
80
+ assert_that(result.success?).is_true
81
+ assert_that(result.sub_results.size).equals(0)
82
+ assert_that(result.all_results.size).equals(1)
83
+ }
84
+ assert_that(tap_result).is_the_same_as(yielded_result)
85
+ end
86
+
87
+ should "call transactions on a transaction receiver" do
88
+ MuchStub.on_call(MuchResult::Transaction, :call) { |call|
89
+ @transaction_call = call
90
+ }
91
+
92
+ receiver1 = Factory.transaction_receiver
93
+ kargs1 = {
94
+ backtrace: Factory.backtrace,
95
+ value: value1
96
+ }
97
+ block1 = -> {}
98
+ subject.transaction(receiver1, **kargs1, &block1)
99
+
100
+ assert_that(@transaction_call.pargs).equals([receiver1])
101
+ assert_that(@transaction_call.kargs).equals(kargs1)
102
+ assert_that(@transaction_call.block).equals(block1)
103
+ end
104
+
105
+ should "halt transactions" do
106
+ receiver1 = Factory.transaction_receiver
107
+ result =
108
+ subject.transaction(receiver1) do |transaction|
109
+ transaction.capture { "something1"}
110
+ transaction.halt
111
+ transaction.capture { "something2" }
112
+ end
113
+
114
+ assert_that(result.sub_results.size).equals(1)
115
+ end
116
+ end
117
+
118
+ class InitTests < UnitTests
119
+ desc "when init"
120
+ subject { unit_class.success }
121
+
122
+ let(:failure1) {
123
+ unit_class.failure(description: Factory.string)
124
+ }
125
+ let(:failure2) {
126
+ unit_class.failure(exception: StandardError.new(Factory.string))
127
+ }
128
+
129
+ should have_imeths :description, :backtrace, :set
130
+ should have_imeths :success?, :failure?
131
+ should have_imeths :capture_for, :capture_for!
132
+ should have_imeths :capture_for_all, :capture_for_all!
133
+ should have_imeths :capture, :capture!
134
+ should have_imeths :capture_all, :capture_all!
135
+ should have_imeths :capture_exception
136
+ should have_imeths :sub_results, :success_sub_results, :failure_sub_results
137
+ should have_imeths :all_results, :all_success_results, :all_failure_results
138
+ should have_imeths :get_for_sub_results
139
+ should have_imeths :get_for_success_sub_results, :get_for_failure_sub_results
140
+ should have_imeths :get_for_all_results
141
+ should have_imeths :get_for_all_success_results, :get_for_all_failure_results
142
+ should have_imeths :to_much_result
143
+
144
+ should "know its attributes" do
145
+ assert_that(subject.description).is_nil
146
+ assert_that(subject.backtrace).is_not_nil
147
+ assert_that(subject.backtrace).is_not_empty
148
+
149
+ result =
150
+ unit_class.success(
151
+ identifier: identifier1,
152
+ description: description1,
153
+ backtrace: backtrace1,
154
+ value: value1
155
+ )
156
+ assert_that(result.identifier).equals(identifier1)
157
+ assert_that(result.description).equals(description1)
158
+ assert_that(result.backtrace).equals(backtrace1)
159
+ assert_that(result.value).equals(value1)
160
+
161
+ exception = result.capture_exception
162
+ assert_that(exception).is_instance_of(MuchResult::Error)
163
+ assert_that(exception.message).equals(description1)
164
+ assert_that(exception.backtrace).equals(backtrace1)
165
+ end
166
+
167
+ should "allow setting arbitrary values" do
168
+ assert_that(subject.other_value).is_nil
169
+
170
+ subject.set(other_value: value1)
171
+ assert_that(subject.other_value).equals(value1)
172
+ end
173
+
174
+ should "capture MuchResults as sub-results" do
175
+ subject.capture_for(unit_class.success(values: { value1: Factory.value }))
176
+ assert_that(subject.success?).is_true
177
+ assert_that(subject.sub_results.size).equals(1)
178
+ assert_that(subject.success_sub_results.size).equals(1)
179
+ assert_that(subject.failure_sub_results.size).equals(0)
180
+ assert_that(subject.get_for_sub_results("values")[:value1]).equals(
181
+ [
182
+ subject.success_sub_results.first.values[:value1]
183
+ ])
184
+ assert_that(subject.get_for_success_sub_results("values")[:value1]).equals(
185
+ [
186
+ subject.success_sub_results.first.values[:value1]
187
+ ])
188
+ assert_that(subject.get_for_failure_sub_results("values")).equals(
189
+ [])
190
+ assert_that(subject.all_results.size).equals(2)
191
+ assert_that(subject.all_success_results.size).equals(2)
192
+ assert_that(subject.all_failure_results.size).equals(0)
193
+ assert_that(subject.get_for_all_results("values")[:value1]).equals(
194
+ [
195
+ nil,
196
+ subject.success_sub_results.first.values[:value1]
197
+ ])
198
+ assert_that(subject.get_for_all_success_results("values")[:value1]).equals(
199
+ [
200
+ nil,
201
+ subject.success_sub_results.first.values[:value1]
202
+ ])
203
+ assert_that(subject.get_for_all_failure_results("values")).equals(
204
+ [])
205
+
206
+ subject.capture_for(unit_class.failure(values: { value1: Factory.value }))
207
+ assert_that(subject.success?).is_false
208
+ assert_that(subject.sub_results.size).equals(2)
209
+ assert_that(subject.success_sub_results.size).equals(1)
210
+ assert_that(subject.failure_sub_results.size).equals(1)
211
+ assert_that(subject.get_for_sub_results("values")[:value1]).equals(
212
+ [
213
+ subject.success_sub_results.first.values[:value1],
214
+ subject.failure_sub_results.first.values[:value1]
215
+ ])
216
+ assert_that(subject.get_for_success_sub_results("values")[:value1]).equals(
217
+ [
218
+ subject.success_sub_results.first.values[:value1]
219
+ ])
220
+ assert_that(subject.get_for_failure_sub_results("values")[:value1]).equals(
221
+ [
222
+ subject.failure_sub_results.first.values[:value1]
223
+ ])
224
+ assert_that(subject.all_results.size).equals(3)
225
+ assert_that(subject.all_success_results.size).equals(1)
226
+ assert_that(subject.all_failure_results.size).equals(2)
227
+ assert_that(subject.get_for_all_results("values")[:value1]).equals(
228
+ [
229
+ nil,
230
+ subject.success_sub_results.first.values[:value1],
231
+ subject.failure_sub_results.first.values[:value1]
232
+ ])
233
+ assert_that(subject.get_for_all_success_results("values")[:value1]).equals(
234
+ [
235
+ subject.success_sub_results.first.values[:value1]
236
+ ])
237
+ assert_that(subject.get_for_all_failure_results("values")[:value1]).equals(
238
+ [
239
+ nil,
240
+ subject.failure_sub_results.first.values[:value1]
241
+ ])
242
+
243
+ result = unit_class.success
244
+
245
+ result.capture_for([true, Factory.integer, Factory.string].sample)
246
+ assert_that(result.success?).is_true
247
+ assert_that(result.sub_results.size).equals(1)
248
+ assert_that(result.success_sub_results.size).equals(1)
249
+ assert_that(result.failure_sub_results.size).equals(0)
250
+ assert_that(result.all_results.size).equals(2)
251
+ assert_that(result.all_success_results.size).equals(2)
252
+ assert_that(result.all_failure_results.size).equals(0)
253
+
254
+ result.capture_for([false, nil].sample)
255
+ assert_that(result.success?).is_false
256
+ assert_that(result.sub_results.size).equals(2)
257
+ assert_that(result.success_sub_results.size).equals(1)
258
+ assert_that(result.failure_sub_results.size).equals(1)
259
+ assert_that(result.all_results.size).equals(3)
260
+ assert_that(result.all_success_results.size).equals(1)
261
+ assert_that(result.all_failure_results.size).equals(2)
262
+
263
+ result = unit_class.success
264
+
265
+ # Test the default built capture exception.
266
+ exception =
267
+ assert_that(-> {
268
+ result.capture_for!(failure1)
269
+ }).raises(MuchResult::Error)
270
+ assert_that(exception.message).equals(failure1.description)
271
+ assert_that(exception.backtrace).equals(failure1.backtrace)
272
+ assert_that(result.success?).is_false
273
+ assert_that(result.sub_results.size).equals(1)
274
+ assert_that(result.success_sub_results.size).equals(0)
275
+ assert_that(result.failure_sub_results.size).equals(1)
276
+ assert_that(result.all_results.size).equals(2)
277
+ assert_that(result.all_success_results.size).equals(0)
278
+ assert_that(result.all_failure_results.size).equals(2)
279
+
280
+ # Test that we prefer any set `result.exception` over the default built
281
+ # capture exception.
282
+ exception =
283
+ assert_that(-> {
284
+ result.capture_for!(failure2)
285
+ }).raises(failure2.exception.class)
286
+ assert_that(exception.message).equals(failure2.exception.message)
287
+ assert_that(exception.backtrace).equals(failure2.exception.backtrace)
288
+ assert_that(result.success?).is_false
289
+ assert_that(result.sub_results.size).equals(2)
290
+ assert_that(result.success_sub_results.size).equals(0)
291
+ assert_that(result.failure_sub_results.size).equals(2)
292
+ assert_that(result.all_results.size).equals(3)
293
+ assert_that(result.all_success_results.size).equals(0)
294
+ assert_that(result.all_failure_results.size).equals(3)
295
+ end
296
+
297
+ should "capture MuchResults from an Array as sub-results" do
298
+ subject.capture_for_all([unit_class.success, unit_class.failure])
299
+ assert_that(subject.success?).is_false
300
+ assert_that(subject.sub_results.size).equals(2)
301
+ assert_that(subject.success_sub_results.size).equals(1)
302
+ assert_that(subject.failure_sub_results.size).equals(1)
303
+ assert_that(subject.all_results.size).equals(3)
304
+ assert_that(subject.all_success_results.size).equals(1)
305
+ assert_that(subject.all_failure_results.size).equals(2)
306
+
307
+ result = unit_class.success
308
+
309
+ result.capture_for_all(
310
+ [
311
+ [true, Factory.integer, Factory.string].sample,
312
+ [false, nil].sample
313
+ ]
314
+ )
315
+ assert_that(result.success?).is_false
316
+ assert_that(result.sub_results.size).equals(2)
317
+ assert_that(result.success_sub_results.size).equals(1)
318
+ assert_that(result.failure_sub_results.size).equals(1)
319
+ assert_that(result.all_results.size).equals(3)
320
+ assert_that(result.all_success_results.size).equals(1)
321
+ assert_that(result.all_failure_results.size).equals(2)
322
+
323
+ result = unit_class.success
324
+
325
+ exception =
326
+ assert_that(-> {
327
+ result.capture_for_all!([failure1, failure2])
328
+ }).raises(MuchResult::Error)
329
+ assert_that(exception.message).equals(failure1.description)
330
+ assert_that(exception.backtrace).equals(failure1.backtrace)
331
+ assert_that(result.success?).is_false
332
+ assert_that(result.sub_results.size).equals(2)
333
+ assert_that(result.success_sub_results.size).equals(0)
334
+ assert_that(result.failure_sub_results.size).equals(2)
335
+ assert_that(result.all_results.size).equals(3)
336
+ assert_that(result.all_success_results.size).equals(0)
337
+ assert_that(result.all_failure_results.size).equals(3)
338
+ end
339
+
340
+ should "capture MuchResults from a block as sub-results" do
341
+ subject.capture { unit_class.success }
342
+ assert_that(subject.success?).is_true
343
+ assert_that(subject.sub_results.size).equals(1)
344
+ assert_that(subject.success_sub_results.size).equals(1)
345
+ assert_that(subject.failure_sub_results.size).equals(0)
346
+ assert_that(subject.all_results.size).equals(2)
347
+ assert_that(subject.all_success_results.size).equals(2)
348
+ assert_that(subject.all_failure_results.size).equals(0)
349
+
350
+ subject.capture { unit_class.failure }
351
+ assert_that(subject.success?).is_false
352
+ assert_that(subject.sub_results.size).equals(2)
353
+ assert_that(subject.success_sub_results.size).equals(1)
354
+ assert_that(subject.failure_sub_results.size).equals(1)
355
+ assert_that(subject.all_results.size).equals(3)
356
+ assert_that(subject.all_success_results.size).equals(1)
357
+ assert_that(subject.all_failure_results.size).equals(2)
358
+
359
+ result = unit_class.success
360
+
361
+ result.capture { [true, Factory.integer, Factory.string].sample }
362
+ assert_that(result.success?).is_true
363
+ assert_that(result.sub_results.size).equals(1)
364
+ assert_that(result.success_sub_results.size).equals(1)
365
+ assert_that(result.failure_sub_results.size).equals(0)
366
+ assert_that(result.all_results.size).equals(2)
367
+ assert_that(result.all_success_results.size).equals(2)
368
+ assert_that(result.all_failure_results.size).equals(0)
369
+
370
+ result.capture { [false, nil].sample }
371
+ assert_that(result.success?).is_false
372
+ assert_that(result.sub_results.size).equals(2)
373
+ assert_that(result.success_sub_results.size).equals(1)
374
+ assert_that(result.failure_sub_results.size).equals(1)
375
+ assert_that(result.all_results.size).equals(3)
376
+ assert_that(result.all_success_results.size).equals(1)
377
+ assert_that(result.all_failure_results.size).equals(2)
378
+
379
+ result = unit_class.success
380
+
381
+ exception =
382
+ assert_that(-> {
383
+ result.capture! { failure1 }
384
+ }).raises(MuchResult::Error)
385
+ assert_that(exception.message).equals(failure1.description)
386
+ assert_that(exception.backtrace).equals(failure1.backtrace)
387
+ assert_that(result.success?).is_false
388
+ assert_that(result.sub_results.size).equals(1)
389
+ assert_that(result.success_sub_results.size).equals(0)
390
+ assert_that(result.failure_sub_results.size).equals(1)
391
+ assert_that(result.all_results.size).equals(2)
392
+ assert_that(result.all_success_results.size).equals(0)
393
+ assert_that(result.all_failure_results.size).equals(2)
394
+ end
395
+
396
+ should "capture MuchResults from a block from an Array as sub-results" do
397
+ subject.capture_all { [unit_class.success, unit_class.failure] }
398
+ assert_that(subject.success?).is_false
399
+ assert_that(subject.sub_results.size).equals(2)
400
+ assert_that(subject.success_sub_results.size).equals(1)
401
+ assert_that(subject.failure_sub_results.size).equals(1)
402
+ assert_that(subject.all_results.size).equals(3)
403
+ assert_that(subject.all_success_results.size).equals(1)
404
+ assert_that(subject.all_failure_results.size).equals(2)
405
+
406
+ result = unit_class.success
407
+
408
+ result.capture_all do
409
+ [
410
+ [true, Factory.integer, Factory.string].sample,
411
+ [false, nil].sample
412
+ ]
413
+ end
414
+ assert_that(result.success?).is_false
415
+ assert_that(result.sub_results.size).equals(2)
416
+ assert_that(result.success_sub_results.size).equals(1)
417
+ assert_that(result.failure_sub_results.size).equals(1)
418
+ assert_that(result.all_results.size).equals(3)
419
+ assert_that(result.all_success_results.size).equals(1)
420
+ assert_that(result.all_failure_results.size).equals(2)
421
+
422
+ result = unit_class.success
423
+
424
+ exception =
425
+ assert_that(-> {
426
+ result.capture_all! { [failure1, failure2] }
427
+ }).raises(MuchResult::Error)
428
+ assert_that(exception.message).equals(failure1.description)
429
+ assert_that(exception.backtrace).equals(failure1.backtrace)
430
+ assert_that(result.success?).is_false
431
+ assert_that(result.sub_results.size).equals(2)
432
+ assert_that(result.success_sub_results.size).equals(0)
433
+ assert_that(result.failure_sub_results.size).equals(2)
434
+ assert_that(result.all_results.size).equals(3)
435
+ assert_that(result.all_success_results.size).equals(0)
436
+ assert_that(result.all_failure_results.size).equals(3)
437
+ end
438
+
439
+ should "convert itself to a MuchResult" do
440
+ assert_that(subject.value).is_nil
441
+
442
+ result = subject.to_much_result(value: value1)
443
+ assert_that(result).is_the_same_as(subject)
444
+ assert_that(subject.value).equals(value1)
445
+ end
446
+ end
447
+ end