composable_operations 0.5.1 → 0.6.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 +4 -4
- data/README.md +3 -1
- data/composable_operations.gemspec +1 -0
- data/lib/composable_operations/matcher.rb +1 -2
- data/lib/composable_operations/matcher/execution.rb +166 -0
- data/lib/composable_operations/operation.rb +14 -9
- data/lib/composable_operations/version.rb +1 -1
- data/spec/composable_operations/composed_operation_spec.rb +3 -1
- data/spec/composable_operations/operation_input_processing_spec.rb +157 -0
- data/spec/composable_operations/operation_spec.rb +7 -17
- data/spec/spec_helper.rb +1 -0
- metadata +20 -5
- data/lib/composable_operations/matcher/fail_to_perform.rb +0 -83
- data/lib/composable_operations/matcher/succeed_to_perform.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 658fbfd45d7aed7d7589d0603270cbac1b3fea39
|
4
|
+
data.tar.gz: bb95ff34e25b6df75249604c9e606ffe2046c136
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 091483e197ccab3c020d27ecfe4e040a9fed7c0b8a0f90a08dbff8d97e75ed80545a642c64b86fab4ea995dea4f1e2d3dee4e9335bfd08b6df85a10a8542332a
|
7
|
+
data.tar.gz: 66b9beda48a6df81f21eddee06f83d0bb0c6f3bdb9c60b6954000fcb0ed59402c277eb5f2a7c0e1ac6a8679285d781cf0457e33a523579e9f1deada49426ffcc
|
data/README.md
CHANGED
@@ -217,13 +217,15 @@ to the initializer.
|
|
217
217
|
```ruby
|
218
218
|
class Indention < ComposableOperations::Operation
|
219
219
|
|
220
|
+
processes :text
|
221
|
+
|
220
222
|
property :indent, default: 2,
|
221
223
|
converts: lambda { |value| value.to_s.to_i },
|
222
224
|
accepts: lambda { |value| value >= 0 },
|
223
225
|
required: true
|
224
226
|
|
225
227
|
def execute
|
226
|
-
|
228
|
+
text.split("\n").map { |line| " " * indent + line }.join("\n")
|
227
229
|
end
|
228
230
|
|
229
231
|
end
|
@@ -22,6 +22,7 @@ multiple of these operations in operation pipelines.}
|
|
22
22
|
spec.add_dependency "smart_properties", "~> 1.0"
|
23
23
|
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "pry", "~> 0.9.0"
|
25
26
|
spec.add_development_dependency "rake"
|
26
27
|
spec.add_development_dependency "rspec", "~> 2.13"
|
27
28
|
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
module ComposableOperations
|
2
|
+
module Matcher
|
3
|
+
module Execution
|
4
|
+
|
5
|
+
class Base
|
6
|
+
|
7
|
+
def and_return(result)
|
8
|
+
@result = result
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
def when_initialized_with(*input)
|
13
|
+
@input = input
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
attr_reader :operation
|
20
|
+
attr_reader :result
|
21
|
+
attr_reader :input
|
22
|
+
|
23
|
+
def operation=(operation)
|
24
|
+
operation = operation.new(*input) if operation.kind_of?(Class)
|
25
|
+
operation.perform
|
26
|
+
@operation = operation
|
27
|
+
end
|
28
|
+
|
29
|
+
def failed?
|
30
|
+
operation.failed?
|
31
|
+
end
|
32
|
+
|
33
|
+
def succeeded?
|
34
|
+
operation.succeeded?
|
35
|
+
end
|
36
|
+
|
37
|
+
def result_as_expected?
|
38
|
+
return true unless result
|
39
|
+
operation.result == result
|
40
|
+
end
|
41
|
+
|
42
|
+
def input_as_text
|
43
|
+
humanize(*input)
|
44
|
+
end
|
45
|
+
|
46
|
+
def result_as_text
|
47
|
+
humanize(result)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def humanize(*args)
|
53
|
+
args = args.map(&:inspect)
|
54
|
+
last_element = args.pop
|
55
|
+
args.length > 0 ? [args.join(", "), last_element].join(" and ") : last_element
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
class SucceedToPerform < Base
|
61
|
+
|
62
|
+
def matches?(operation)
|
63
|
+
self.operation = operation
|
64
|
+
succeeded? && result_as_expected?
|
65
|
+
end
|
66
|
+
|
67
|
+
def description
|
68
|
+
description = "succeed to perform"
|
69
|
+
description += " when initialized with custom input (#{input_as_text})" if input
|
70
|
+
description += " and return the expected result (#{result_as_text})" if result
|
71
|
+
description
|
72
|
+
end
|
73
|
+
|
74
|
+
def failure_message
|
75
|
+
"the operation failed to perform for the following reason(s):\n#{failure_reasons}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def negative_failure_message
|
79
|
+
"the operation succeeded unexpectedly"
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def failure_reasons
|
85
|
+
reasons = []
|
86
|
+
reasons << "it did not succeed at all" unless succeeded?
|
87
|
+
unless result_as_expected?
|
88
|
+
reasons << [
|
89
|
+
"it did not return the expected result",
|
90
|
+
"Expected: #{result.inspect}",
|
91
|
+
"Got: #{operation.result.inspect}"
|
92
|
+
].join("\n\t ")
|
93
|
+
end
|
94
|
+
reasons.map { |r| "\t- #{r}" }.join("\n")
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
class FailToPerform < Base
|
100
|
+
|
101
|
+
def matches?(operation)
|
102
|
+
self.operation = operation
|
103
|
+
failed? && result_as_expected? && message_as_expected?
|
104
|
+
end
|
105
|
+
|
106
|
+
def because(message)
|
107
|
+
@message = message
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
def description
|
112
|
+
description = "fail to perform"
|
113
|
+
description += " because #{message}" if message
|
114
|
+
description += " when initialized with custom input (#{input_as_text})" if input
|
115
|
+
description += " and return the expected result (#{result_as_text})" if result
|
116
|
+
description
|
117
|
+
end
|
118
|
+
|
119
|
+
def failure_message
|
120
|
+
"the operation did not fail to perform for the following reason(s):\n#{failure_reasons}"
|
121
|
+
end
|
122
|
+
|
123
|
+
def negative_failure_message
|
124
|
+
"the operation failed unexpectedly"
|
125
|
+
end
|
126
|
+
|
127
|
+
protected
|
128
|
+
|
129
|
+
attr_reader :message
|
130
|
+
|
131
|
+
def message_as_expected?
|
132
|
+
return true unless message
|
133
|
+
operation.message == message
|
134
|
+
end
|
135
|
+
|
136
|
+
def failure_reasons
|
137
|
+
reasons = []
|
138
|
+
reasons << "it did not fail at all" unless failed?
|
139
|
+
reasons << "its message was not as expected" unless message_as_expected?
|
140
|
+
unless result_as_expected?
|
141
|
+
reasons << [
|
142
|
+
"it did not return the expected result",
|
143
|
+
"Expected: #{result.inspect}",
|
144
|
+
"Got: #{operation.result.inspect}"
|
145
|
+
].join("\n\t ")
|
146
|
+
end
|
147
|
+
reasons.map { |r| "\t- #{r}" }.join("\n")
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
def succeed_to_perform
|
153
|
+
SucceedToPerform.new
|
154
|
+
end
|
155
|
+
|
156
|
+
def fail_to_perform
|
157
|
+
FailToPerform.new
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
RSpec.configure do |config|
|
165
|
+
config.include ComposableOperations::Matcher::Execution
|
166
|
+
end
|
@@ -5,6 +5,12 @@ module ComposableOperations
|
|
5
5
|
|
6
6
|
class << self
|
7
7
|
|
8
|
+
attr_writer :arity
|
9
|
+
|
10
|
+
def arity
|
11
|
+
@arity || 0
|
12
|
+
end
|
13
|
+
|
8
14
|
def perform(*args)
|
9
15
|
operation = new(*args)
|
10
16
|
operation.perform
|
@@ -51,11 +57,11 @@ module ComposableOperations
|
|
51
57
|
end
|
52
58
|
|
53
59
|
def processes(*names)
|
60
|
+
self.arity = names.length
|
61
|
+
|
54
62
|
case names.length
|
55
63
|
when 0
|
56
64
|
raise ArgumentError, "#{self}.#{__callee__} expects at least one argument"
|
57
|
-
when 1
|
58
|
-
alias_method names[0].to_sym, :input
|
59
65
|
else
|
60
66
|
names.each_with_index do |name, index|
|
61
67
|
define_method(name) { input[index] }
|
@@ -82,13 +88,12 @@ module ComposableOperations
|
|
82
88
|
attr_reader :backtrace
|
83
89
|
|
84
90
|
def initialize(*args)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
91
|
+
named_input_parameters = args.shift(self.class.arity)
|
92
|
+
options = args.last.kind_of?(Hash) ? args.pop : {}
|
93
|
+
unnamed_input_parameters = args
|
94
|
+
|
95
|
+
@input = named_input_parameters + unnamed_input_parameters
|
96
|
+
super(options)
|
92
97
|
end
|
93
98
|
|
94
99
|
def failed?
|
@@ -16,12 +16,14 @@ describe ComposableOperations::ComposedOperation do
|
|
16
16
|
|
17
17
|
let(:string_capitalizer) do
|
18
18
|
Class.new(ComposableOperations::Operation) do
|
19
|
+
processes :text
|
20
|
+
|
19
21
|
def self.name
|
20
22
|
"StringCapitalizer"
|
21
23
|
end
|
22
24
|
|
23
25
|
def execute
|
24
|
-
|
26
|
+
text.upcase
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ComposableOperations::Operation, "input processing:" do
|
4
|
+
|
5
|
+
describe "An operation that takes a Hash as input" do
|
6
|
+
|
7
|
+
let(:input) { {food: "chunky bacon" } }
|
8
|
+
|
9
|
+
subject(:operation) do
|
10
|
+
Class.new(described_class) do
|
11
|
+
processes :some_hash
|
12
|
+
def execute
|
13
|
+
some_hash
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
it { should succeed_to_perform.when_initialized_with(input).and_return(input) }
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "An operation that takes no arguments except for a Hash of additional options" do
|
23
|
+
|
24
|
+
subject(:operation) do
|
25
|
+
Class.new(described_class) do
|
26
|
+
def execute
|
27
|
+
input
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it { should succeed_to_perform.when_initialized_with(key: :value).and_return([]) }
|
33
|
+
it { should succeed_to_perform.when_initialized_with(1, 2, 3, key: :value).and_return([1, 2, 3]) }
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "An operation that takes a Hash as input and an Hash of additional options" do
|
38
|
+
|
39
|
+
let(:input) { { food: nil } }
|
40
|
+
|
41
|
+
subject(:operation) do
|
42
|
+
Class.new(described_class) do
|
43
|
+
processes :some_hash
|
44
|
+
property :default_food, default: "chunky bacon"
|
45
|
+
def execute
|
46
|
+
some_hash[:food] ||= default_food
|
47
|
+
some_hash
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it { should succeed_to_perform.when_initialized_with(input, default_food: "bananas").and_return(food: "bananas") }
|
53
|
+
it { should succeed_to_perform.when_initialized_with(input).and_return(food: "chunky bacon") }
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "An operation that takes two named arguments as input and sums them up" do
|
58
|
+
|
59
|
+
subject(:operation) do
|
60
|
+
Class.new(described_class) do
|
61
|
+
processes :first_operand, :second_operand
|
62
|
+
def execute
|
63
|
+
first_operand + second_operand
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it { should succeed_to_perform.when_initialized_with(1, 2).and_return(3) }
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "An operation that takes two named arguments as input and simply returns all input arguments as output" do
|
73
|
+
|
74
|
+
subject(:operation) do
|
75
|
+
Class.new(described_class) do
|
76
|
+
processes :first_operand, :second_operand
|
77
|
+
def execute
|
78
|
+
input
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it { should succeed_to_perform.when_initialized_with(1, 2).and_return([1, 2]) }
|
84
|
+
it { should succeed_to_perform.when_initialized_with(1, 2, 3).and_return([1, 2, 3]) }
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "An operation that takes multiple arguments as input where the last of these arguments is a Hash" do
|
89
|
+
|
90
|
+
subject(:operation) do
|
91
|
+
Class.new(described_class) do
|
92
|
+
processes :first_operand, :second_operand
|
93
|
+
property :operator, default: :+, converts: :to_sym, required: true
|
94
|
+
def execute
|
95
|
+
first_operand.public_send(operator, second_operand)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
it { should succeed_to_perform.when_initialized_with(1, 2).and_return(3) }
|
101
|
+
it { should succeed_to_perform.when_initialized_with(1, 2, operator: :*).and_return(2) }
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "An operation that takes multiple arguments as input where the last of these arguments is a Hash, as well as, a Hash of additional options" do
|
106
|
+
|
107
|
+
subject(:operation) do
|
108
|
+
Class.new(described_class) do
|
109
|
+
processes :some_value, :yet_another_value, :a_hash
|
110
|
+
def execute
|
111
|
+
a_hash
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
it { should succeed_to_perform.when_initialized_with(1, 2, {food: "chunky bacon"}, { additional: :options }).and_return(food: "chunky bacon") }
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
describe ComposableOperations::ComposedOperation, "input processing:" do
|
123
|
+
|
124
|
+
describe "A composed operation that consists of a producer and a consumer" do
|
125
|
+
|
126
|
+
let(:producer) do
|
127
|
+
Class.new(ComposableOperations::Operation) do
|
128
|
+
def execute
|
129
|
+
return 1, 2
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
let(:consumer) do
|
135
|
+
Class.new(ComposableOperations::Operation) do
|
136
|
+
processes :first_operand, :second_operand
|
137
|
+
def execute
|
138
|
+
first_operand + second_operand
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
subject(:operation) do
|
144
|
+
producer = self.producer
|
145
|
+
consumer = self.consumer
|
146
|
+
|
147
|
+
Class.new(described_class) do
|
148
|
+
use producer
|
149
|
+
use consumer
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
it { should succeed_to_perform.and_return(3) }
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
@@ -22,7 +22,7 @@ describe ComposableOperations::Operation do
|
|
22
22
|
let(:halting_operation) do
|
23
23
|
Class.new(described_class) do
|
24
24
|
def execute
|
25
|
-
halt "Full stop!", input
|
25
|
+
halt "Full stop!", input.first
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -169,16 +169,12 @@ describe ComposableOperations::Operation do
|
|
169
169
|
|
170
170
|
context "when extended with a finalizer that checks that the result is not an empty string" do
|
171
171
|
|
172
|
-
|
172
|
+
subject(:simple_operation_with_sanity_check) do
|
173
173
|
Class.new(simple_operation) do
|
174
174
|
after { fail "the operational result is an empty string" if self.result == "" }
|
175
175
|
end
|
176
176
|
end
|
177
177
|
|
178
|
-
subject(:simple_operation_with_sanity_check_instance) do
|
179
|
-
simple_operation_with_sanity_check.new
|
180
|
-
end
|
181
|
-
|
182
178
|
it { should fail_to_perform.because("the operational result is an empty string") }
|
183
179
|
|
184
180
|
end
|
@@ -189,21 +185,17 @@ describe ComposableOperations::Operation do
|
|
189
185
|
|
190
186
|
subject(:string_multiplier) do
|
191
187
|
Class.new(described_class) do
|
188
|
+
processes :text
|
192
189
|
property :multiplier, :default => 3
|
193
190
|
|
194
191
|
def execute
|
195
|
-
|
192
|
+
text.to_s * multiplier
|
196
193
|
end
|
197
194
|
end
|
198
195
|
end
|
199
196
|
|
200
|
-
it
|
201
|
-
|
202
|
-
end
|
203
|
-
|
204
|
-
it "should allow to overwrite default settings" do
|
205
|
-
string_multiplier.perform("-", :multiplier => 5).should be == "-----"
|
206
|
-
end
|
197
|
+
it { should succeed_to_perform.when_initialized_with("-").and_return("---") }
|
198
|
+
it { should succeed_to_perform.when_initialized_with("-", multiplier: 5).and_return("-----") }
|
207
199
|
|
208
200
|
end
|
209
201
|
|
@@ -219,9 +211,7 @@ describe ComposableOperations::Operation do
|
|
219
211
|
end
|
220
212
|
end
|
221
213
|
|
222
|
-
it
|
223
|
-
string_multiplier.perform(["-", 3]).should be == "---"
|
224
|
-
end
|
214
|
+
it { should succeed_to_perform.when_initialized_with("-", 3).and_return("---") }
|
225
215
|
|
226
216
|
end
|
227
217
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: composable_operations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Tennhard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-08-
|
11
|
+
date: 2013-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: smart_properties
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.9.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.9.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,14 +98,14 @@ files:
|
|
84
98
|
- lib/composable_operations.rb
|
85
99
|
- lib/composable_operations/composed_operation.rb
|
86
100
|
- lib/composable_operations/matcher.rb
|
87
|
-
- lib/composable_operations/matcher/
|
88
|
-
- lib/composable_operations/matcher/succeed_to_perform.rb
|
101
|
+
- lib/composable_operations/matcher/execution.rb
|
89
102
|
- lib/composable_operations/matcher/utilize_operation.rb
|
90
103
|
- lib/composable_operations/operation.rb
|
91
104
|
- lib/composable_operations/operation_error.rb
|
92
105
|
- lib/composable_operations/version.rb
|
93
106
|
- spec/composable_operations/composed_operation_spec.rb
|
94
107
|
- spec/composable_operations/control_flow_spec.rb
|
108
|
+
- spec/composable_operations/operation_input_processing_spec.rb
|
95
109
|
- spec/composable_operations/operation_spec.rb
|
96
110
|
- spec/spec_helper.rb
|
97
111
|
homepage: http://github.com/t6d/composable_operations
|
@@ -114,12 +128,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
114
128
|
version: '0'
|
115
129
|
requirements: []
|
116
130
|
rubyforge_project:
|
117
|
-
rubygems_version: 2.0.
|
131
|
+
rubygems_version: 2.0.6
|
118
132
|
signing_key:
|
119
133
|
specification_version: 4
|
120
134
|
summary: Tool set for operation pipelines.
|
121
135
|
test_files:
|
122
136
|
- spec/composable_operations/composed_operation_spec.rb
|
123
137
|
- spec/composable_operations/control_flow_spec.rb
|
138
|
+
- spec/composable_operations/operation_input_processing_spec.rb
|
124
139
|
- spec/composable_operations/operation_spec.rb
|
125
140
|
- spec/spec_helper.rb
|
@@ -1,83 +0,0 @@
|
|
1
|
-
module ComposableOperations
|
2
|
-
module Matcher
|
3
|
-
module FailToPerform
|
4
|
-
class Matcher
|
5
|
-
|
6
|
-
def matches?(operation)
|
7
|
-
self.operation = operation
|
8
|
-
failed? && result_as_expected? && message_as_expected?
|
9
|
-
end
|
10
|
-
|
11
|
-
def because(message)
|
12
|
-
@message = message
|
13
|
-
self
|
14
|
-
end
|
15
|
-
|
16
|
-
def and_return(result)
|
17
|
-
@result = result
|
18
|
-
self
|
19
|
-
end
|
20
|
-
|
21
|
-
def description
|
22
|
-
description = "fail to perform"
|
23
|
-
description += " because #{message}" if message
|
24
|
-
description += " and return the expected result" if result
|
25
|
-
description
|
26
|
-
end
|
27
|
-
|
28
|
-
def failure_message
|
29
|
-
"the operation did not fail to perform for the following reason(s):\n#{failure_reasons}"
|
30
|
-
end
|
31
|
-
|
32
|
-
def negative_failure_message
|
33
|
-
"the operation failed unexpectedly"
|
34
|
-
end
|
35
|
-
|
36
|
-
protected
|
37
|
-
|
38
|
-
attr_reader :operation
|
39
|
-
attr_reader :message
|
40
|
-
attr_reader :result
|
41
|
-
|
42
|
-
def operation=(operation)
|
43
|
-
operation.perform
|
44
|
-
@operation = operation
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
def failed?
|
50
|
-
operation.failed?
|
51
|
-
end
|
52
|
-
|
53
|
-
def message_as_expected?
|
54
|
-
return true unless message
|
55
|
-
operation.message == message
|
56
|
-
end
|
57
|
-
|
58
|
-
def result_as_expected?
|
59
|
-
return true unless result
|
60
|
-
operation.result == result
|
61
|
-
end
|
62
|
-
|
63
|
-
def failure_reasons
|
64
|
-
reasons = []
|
65
|
-
reasons << "it did not fail at all" unless failed?
|
66
|
-
reasons << "its message was not as expected" unless message_as_expected?
|
67
|
-
reasons << "it did not return the expected result" unless result_as_expected?
|
68
|
-
reasons.map { |r| "\t- #{r}" }.join("\n")
|
69
|
-
end
|
70
|
-
|
71
|
-
end
|
72
|
-
|
73
|
-
def fail_to_perform
|
74
|
-
Matcher.new
|
75
|
-
end
|
76
|
-
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
RSpec.configure do |config|
|
82
|
-
config.include ComposableOperations::Matcher::FailToPerform
|
83
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
module ComposableOperations
|
2
|
-
module Matcher
|
3
|
-
module SucceedToPerform
|
4
|
-
class Matcher
|
5
|
-
|
6
|
-
def matches?(operation)
|
7
|
-
self.operation = operation
|
8
|
-
succeeded? && result_as_expected?
|
9
|
-
end
|
10
|
-
|
11
|
-
def and_return(result)
|
12
|
-
@result = result
|
13
|
-
self
|
14
|
-
end
|
15
|
-
|
16
|
-
def description
|
17
|
-
description = "succeed to perform"
|
18
|
-
description += " and return the expected result" if result
|
19
|
-
description
|
20
|
-
end
|
21
|
-
|
22
|
-
def failure_message
|
23
|
-
"the operation failed to perform for the following reason(s):\n#{failure_reasons}"
|
24
|
-
end
|
25
|
-
|
26
|
-
def negative_failure_message
|
27
|
-
"the operation succeeded unexpectedly"
|
28
|
-
end
|
29
|
-
|
30
|
-
protected
|
31
|
-
|
32
|
-
attr_reader :operation
|
33
|
-
attr_reader :result
|
34
|
-
|
35
|
-
def operation=(operation)
|
36
|
-
operation.perform
|
37
|
-
@operation = operation
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def succeeded?
|
43
|
-
operation.succeeded?
|
44
|
-
end
|
45
|
-
|
46
|
-
def result_as_expected?
|
47
|
-
return true unless result
|
48
|
-
operation.result == result
|
49
|
-
end
|
50
|
-
|
51
|
-
def failure_reasons
|
52
|
-
reasons = []
|
53
|
-
reasons << "it did not succeed at all" unless succeeded?
|
54
|
-
reasons << "it did not return the expected result" unless result_as_expected?
|
55
|
-
reasons.map { |r| "\t- #{r}" }.join("\n")
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
def succeed_to_perform
|
61
|
-
Matcher.new
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
RSpec.configure do |config|
|
68
|
-
config.include ComposableOperations::Matcher::SucceedToPerform
|
69
|
-
end
|
70
|
-
|