-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathpipe_spec.rb
More file actions
203 lines (158 loc) · 5.54 KB
/
pipe_spec.rb
File metadata and controls
203 lines (158 loc) · 5.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
require 'spec_helper'
# Parent is a dummy test class.
class Parent < Pipes::Pipe
require_context :flow
def call
flow.push(self.class.name)
end
end # class Parent
class Child < Parent; end
class Grandchild < Parent; end
class GrandGrandchild < Parent; end
# BadApple will break.
class BadApple < Pipes::Pipe
def call
fail StandardError
end
end
class ProvidingChild < Parent
provide_context :bacon
def call
super
add(bacon: true)
end
end # class ProvidingChild
class ProvidingNumericChild < Parent
provide_context bacon: Numeric
def call
super
add(bacon: 4)
end
end # class ProvidingNumericChild
class NotProvidingChild < Parent
provide_context :bacon
end # class NotProvidingChild
class ProvidingInvalidChild < Parent
provide_context bacon: Numeric
def call
super
add(bacon: "yes, please")
end
end # class ProvidingInvalidChild
class RequiringChild < Parent
require_context :bacon
end # class RequiringChild
class RequiringNumericChild < Parent
require_context bacon: Numeric
end # class RequiringNumericChild
# NoMethodPipe will break with NoMethodError.
class NoMethodPipe < Pipes::Pipe; end
describe Pipes::Pipe do
let(:ctx) { Pipes::Context.new({}, flow: []) }
subject { pipe.call(ctx) }
describe 'normal flow' do
let(:pipe) { Parent | Child | Grandchild }
it 'executes the pipe left to right' do
expect { subject }.to change { ctx.flow }
.from([]).to %w(Parent Child Grandchild)
end
end # describe 'normal flow'
describe 'pipe raising an exception' do
let(:pipe) { Parent | BadApple | Child }
it 'raises StandardError' do
expect { pipe.call(ctx) }.to raise_error StandardError
end
it 'stores the result of execution so far in the context' do
# rubocop:disable Style/RescueModifier
expect { pipe.call(ctx) rescue nil }
.to change { ctx.flow }
.from([]).to(['Parent'])
# rubocop:enable Style/RescueModifier
end
end # describe 'pipe raising an exception'
describe '.provide_context' do
context 'when context element provided' do
let(:pipe) { Parent | ProvidingChild }
it 'does not raise' do
expect { subject }.to_not raise_error
end
end # context 'when context element provided'
context 'when context element not provided' do
let(:pipe) { Parent | NotProvidingChild }
it 'raises MissingContext' do
expect { subject }.to raise_error Pipes::MissingContext
end
end # context 'when context element not provided'
context 'when context element with invalid type provided' do
let(:pipe) { Parent | ProvidingInvalidChild }
it 'raises InvalidType' do
expect { subject }.to raise_error Pipes::InvalidType
end
end # context 'when context element with invalid type provided'
context 'when context element with valid type provided' do
let(:pipe) { Parent | ProvidingNumericChild }
it 'does not raise' do
expect { subject }.to_not raise_error
end
end # context 'when context element with valid type provided'
end # describe '.provide_context'
describe '.require_context' do
context 'when required context element present' do
let(:pipe) { ProvidingChild | RequiringChild }
it 'does not raise' do
expect { subject }.to_not raise_error
end
end # context 'when required context element present'
context 'when required context element missing' do
let(:pipe) { Parent | RequiringChild }
it 'raises MissingContext' do
expect { subject }.to raise_error Pipes::MissingContext
end
end # context 'when context element missing'
context 'when required context element present with invalid type' do
let(:pipe) { ProvidingInvalidChild | RequiringNumericChild }
it 'raises InvalidType' do
expect { subject }.to raise_error Pipes::InvalidType
end
end # context 'when context element present with invalid type'
context 'when required context element present with valid type' do
let(:pipe) { ProvidingNumericChild | RequiringNumericChild }
it 'raises InvalidType' do
expect { subject }.to_not raise_error
end
end # context 'when context element present with valid type'
end # describe '.provide_context'
describe 'pipes declared using Pipe::Closure' do
let(:dynamic_grandchild) do
Pipes::Closure.define { context.flow << 'bacon' }
end
let(:pipe) { Parent | dynamic_grandchild | Child }
it 'behaves as with normal pipes' do
expect { subject }
.to change { ctx.flow }
.from([]).to %w(Parent bacon Child)
end
end # describe 'pipes declared using Pipe::Closure'
describe 'pipe with a missing `call` method' do
let(:pipe) { Parent | Child | NoMethodPipe }
it 'raises a Pipes::MissingCallMethod error' do
expect { subject }.to raise_error Pipes::MissingCallMethod
end
end # describe 'pipe with a missing `call` method'
describe 'combined pipes' do
let(:first) { Parent | Child }
let(:second) { Grandchild | GrandGrandchild }
let(:pipe) { first | second }
it 'behaves as with normal pipes' do
expect { subject }
.to change { ctx.flow }
.from([]).to %w(Parent Child Grandchild GrandGrandchild)
end
describe 'broken combination' do
let(:second) { NoMethodPipe | Grandchild }
it 'raises error from a broken pipe' do
expect { subject }.to raise_error Pipes::MissingCallMethod
end
end # describe 'broken combination'
end # describe 'combined pipes'
end # describe Pipes::Pipe