substation 0.0.10.beta2 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +7 -3
- data/Changelog.md +99 -24
- data/Gemfile +8 -1
- data/Gemfile.devtools +37 -21
- data/Guardfile +1 -1
- data/README.md +118 -46
- data/TODO.md +1 -0
- data/config/flay.yml +2 -2
- data/config/flog.yml +1 -1
- data/config/reek.yml +41 -16
- data/config/rubocop.yml +44 -0
- data/config/yardstick.yml +1 -1
- data/lib/substation.rb +41 -5
- data/lib/substation/chain.rb +73 -84
- data/lib/substation/chain/definition.rb +147 -0
- data/lib/substation/chain/dsl.rb +150 -112
- data/lib/substation/chain/dsl/config.rb +55 -0
- data/lib/substation/chain/dsl/module_builder.rb +84 -0
- data/lib/substation/dispatcher.rb +20 -229
- data/lib/substation/dsl/guard.rb +96 -0
- data/lib/substation/dsl/registry.rb +181 -0
- data/lib/substation/environment.rb +126 -23
- data/lib/substation/environment/dsl.rb +31 -12
- data/lib/substation/processor.rb +238 -7
- data/lib/substation/processor/builder.rb +26 -0
- data/lib/substation/processor/config.rb +24 -0
- data/lib/substation/processor/evaluator.rb +66 -42
- data/lib/substation/processor/evaluator/handler.rb +54 -0
- data/lib/substation/processor/evaluator/result.rb +24 -0
- data/lib/substation/processor/executor.rb +46 -0
- data/lib/substation/processor/nest.rb +40 -0
- data/lib/substation/processor/transformer.rb +46 -0
- data/lib/substation/processor/wrapper.rb +16 -5
- data/lib/substation/request.rb +29 -27
- data/lib/substation/response.rb +19 -34
- data/lib/substation/response/api.rb +37 -0
- data/lib/substation/response/exception.rb +20 -0
- data/lib/substation/response/exception/output.rb +59 -0
- data/lib/substation/response/failure.rb +11 -0
- data/lib/substation/response/success.rb +11 -0
- data/lib/substation/version.rb +3 -1
- data/spec/demo/core.rb +64 -0
- data/spec/demo/core/action.rb +49 -0
- data/spec/demo/core/action/create_person.rb +28 -0
- data/spec/demo/core/errors.rb +16 -0
- data/spec/demo/core/facade.rb +38 -0
- data/spec/demo/core/handler.rb +21 -0
- data/spec/demo/core/handler/acceptor.rb +47 -0
- data/spec/demo/core/handler/authenticator.rb +36 -0
- data/spec/demo/core/handler/authorizer.rb +38 -0
- data/spec/demo/core/input.rb +15 -0
- data/spec/demo/core/observers.rb +10 -0
- data/spec/demo/core/validator.rb +21 -0
- data/spec/demo/domain/actor.rb +29 -0
- data/spec/demo/domain/dto/person.rb +18 -0
- data/spec/demo/domain/environment.rb +55 -0
- data/spec/demo/domain/storage.rb +49 -0
- data/spec/demo/web.rb +26 -0
- data/spec/demo/web/errors.rb +9 -0
- data/spec/demo/web/facade.rb +60 -0
- data/spec/demo/web/handler/deserializer.rb +36 -0
- data/spec/demo/web/presenter.rb +38 -0
- data/spec/demo/web/presenter/person.rb +19 -0
- data/spec/demo/web/renderer.rb +45 -0
- data/spec/demo/web/sanitizer.rb +35 -0
- data/spec/demo/web/sanitizer/person.rb +20 -0
- data/spec/demo/web/views.rb +28 -0
- data/spec/integration/demo/core_spec.rb +97 -0
- data/spec/integration/demo/web_spec.rb +114 -0
- data/spec/shared/context/integration/demo.rb +33 -0
- data/spec/shared/context/unit/chain.rb +13 -0
- data/spec/shared/context/unit/processor.rb +58 -0
- data/spec/shared/context/unit/request.rb +8 -0
- data/spec/shared/examples/integration/demo.rb +35 -0
- data/spec/shared/examples/unit/processor.rb +72 -0
- data/spec/spec_helper.rb +52 -23
- data/spec/unit/substation/chain/definition_spec.rb +141 -0
- data/spec/unit/substation/chain/dsl/config/dsl_module_spec.rb +13 -0
- data/spec/unit/substation/chain/dsl/config/registry_spec.rb +13 -0
- data/spec/unit/substation/chain/dsl/config_spec.rb +18 -0
- data/spec/unit/substation/chain/dsl/module_builder_spec.rb +77 -0
- data/spec/unit/substation/chain/dsl_spec.rb +175 -0
- data/spec/unit/substation/chain_spec.rb +303 -0
- data/spec/unit/substation/dispatcher_spec.rb +68 -0
- data/spec/unit/substation/dsl/guard_spec.rb +72 -0
- data/spec/unit/substation/dsl/registry_spec.rb +181 -0
- data/spec/unit/substation/environment/dsl_spec.rb +156 -0
- data/spec/unit/substation/environment_spec.rb +259 -0
- data/spec/unit/substation/processor/builder_spec.rb +21 -0
- data/spec/unit/substation/processor/config_spec.rb +40 -0
- data/spec/unit/substation/processor/evaluator/handler_spec.rb +20 -0
- data/spec/unit/substation/processor/evaluator/pivot_spec.rb +42 -0
- data/spec/unit/substation/processor/evaluator/request_spec.rb +11 -0
- data/spec/unit/substation/processor/evaluator/result/failure_spec.rb +14 -0
- data/spec/unit/substation/processor/evaluator/result/success_spec.rb +14 -0
- data/spec/unit/substation/processor/evaluator/result_spec.rb +13 -0
- data/spec/unit/substation/processor/evaluator_spec.rb +18 -0
- data/spec/unit/substation/processor/executor/null_spec.rb +25 -0
- data/spec/unit/substation/processor/executor_spec.rb +32 -0
- data/spec/unit/substation/processor/fallible_spec.rb +24 -0
- data/spec/unit/substation/processor/incoming_spec.rb +17 -0
- data/spec/unit/substation/processor/nest/incoming_spec.rb +56 -0
- data/spec/unit/substation/processor/nest_spec.rb +6 -0
- data/spec/unit/substation/processor/outgoing_spec.rb +47 -0
- data/spec/unit/substation/processor/transformer/incoming_spec.rb +17 -0
- data/spec/unit/substation/processor/transformer/outgoing_spec.rb +17 -0
- data/spec/unit/substation/processor/wrapper/incoming_spec.rb +15 -0
- data/spec/unit/substation/processor/wrapper/outgoing_spec.rb +15 -0
- data/spec/unit/substation/processor/wrapper_spec.rb +24 -0
- data/spec/unit/substation/processor_spec.rb +68 -0
- data/spec/unit/substation/request_spec.rb +70 -0
- data/spec/unit/substation/response/api_spec.rb +22 -0
- data/spec/unit/substation/response/exception/output_spec.rb +46 -0
- data/spec/unit/substation/response/exception_spec.rb +25 -0
- data/spec/unit/substation/response/failure_spec.rb +25 -0
- data/spec/unit/substation/response/success_spec.rb +24 -0
- data/spec/unit/substation/response_spec.rb +73 -0
- data/substation.gemspec +7 -6
- metadata +157 -67
- checksums.yaml +0 -7
- data/TODO +0 -0
- data/lib/substation/observer.rb +0 -66
- data/lib/substation/processor/pivot.rb +0 -25
- data/lib/substation/utils.rb +0 -68
- data/spec/integration/substation/dispatcher/call_spec.rb +0 -260
- data/spec/unit/substation/chain/call_spec.rb +0 -63
- data/spec/unit/substation/chain/dsl/builder/class_methods/call_spec.rb +0 -19
- data/spec/unit/substation/chain/dsl/builder/dsl_spec.rb +0 -21
- data/spec/unit/substation/chain/dsl/builder/failure_chain_spec.rb +0 -30
- data/spec/unit/substation/chain/dsl/chain_spec.rb +0 -15
- data/spec/unit/substation/chain/dsl/class_methods/processors_spec.rb +0 -24
- data/spec/unit/substation/chain/dsl/initialize_spec.rb +0 -19
- data/spec/unit/substation/chain/dsl/processors_spec.rb +0 -42
- data/spec/unit/substation/chain/dsl/use_spec.rb +0 -14
- data/spec/unit/substation/chain/each_spec.rb +0 -46
- data/spec/unit/substation/chain/incoming/result_spec.rb +0 -21
- data/spec/unit/substation/chain/outgoing/call_spec.rb +0 -25
- data/spec/unit/substation/chain/outgoing/result_spec.rb +0 -21
- data/spec/unit/substation/dispatcher/action/call_spec.rb +0 -23
- data/spec/unit/substation/dispatcher/action/class_methods/coerce_spec.rb +0 -61
- data/spec/unit/substation/dispatcher/action_names_spec.rb +0 -14
- data/spec/unit/substation/dispatcher/call_spec.rb +0 -47
- data/spec/unit/substation/dispatcher/class_methods/coerce_spec.rb +0 -20
- data/spec/unit/substation/environment/chain_spec.rb +0 -50
- data/spec/unit/substation/environment/class_methods/build_spec.rb +0 -11
- data/spec/unit/substation/environment/dsl/class_methods/registry_spec.rb +0 -18
- data/spec/unit/substation/environment/dsl/register_spec.rb +0 -14
- data/spec/unit/substation/environment/dsl/registry_spec.rb +0 -19
- data/spec/unit/substation/observer/chain/call_spec.rb +0 -26
- data/spec/unit/substation/observer/class_methods/coerce_spec.rb +0 -33
- data/spec/unit/substation/observer/null/call_spec.rb +0 -12
- data/spec/unit/substation/processor/evaluator/call_spec.rb +0 -49
- data/spec/unit/substation/processor/pivot/call_spec.rb +0 -17
- data/spec/unit/substation/processor/wrapper/call_spec.rb +0 -20
- data/spec/unit/substation/request/env_spec.rb +0 -14
- data/spec/unit/substation/request/error_spec.rb +0 -15
- data/spec/unit/substation/request/input_spec.rb +0 -14
- data/spec/unit/substation/request/success_spec.rb +0 -15
- data/spec/unit/substation/response/env_spec.rb +0 -16
- data/spec/unit/substation/response/failure/success_predicate_spec.rb +0 -15
- data/spec/unit/substation/response/input_spec.rb +0 -16
- data/spec/unit/substation/response/output_spec.rb +0 -16
- data/spec/unit/substation/response/request_spec.rb +0 -16
- data/spec/unit/substation/response/success/success_predicate_spec.rb +0 -15
- data/spec/unit/substation/utils/class_methods/coerce_callable_spec.rb +0 -46
- data/spec/unit/substation/utils/class_methods/const_get_spec.rb +0 -46
- data/spec/unit/substation/utils/class_methods/symbolize_keys_spec.rb +0 -20
@@ -0,0 +1,303 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Chain do
|
6
|
+
describe '#call' do
|
7
|
+
|
8
|
+
subject { object.call(request) }
|
9
|
+
|
10
|
+
include_context 'Request#initialize'
|
11
|
+
|
12
|
+
let(:object) { described_class.new(processors, exception_chain) }
|
13
|
+
let(:exception_chain) { double(:call => response) }
|
14
|
+
let(:processors) { [ processor_1, processor_2, processor_3 ] }
|
15
|
+
|
16
|
+
let(:processor_1_name) { double }
|
17
|
+
let(:processor_2_name) { double }
|
18
|
+
let(:processor_3_name) { double }
|
19
|
+
|
20
|
+
let(:processor_config) { Processor::Config.new(handler, failure_chain, executor) }
|
21
|
+
let(:handler) { double('handler') }
|
22
|
+
let(:failure_chain) { double(:call => failure_response) }
|
23
|
+
let(:failure_response) { double }
|
24
|
+
let(:executor) { Processor::Executor::NULL }
|
25
|
+
|
26
|
+
context 'when all processors are successful' do
|
27
|
+
let(:processor_1) {
|
28
|
+
Class.new {
|
29
|
+
include Substation::Processor::Incoming
|
30
|
+
def call(request)
|
31
|
+
request.success(:success_1)
|
32
|
+
end
|
33
|
+
}.new(processor_1_name, handler, processor_config)
|
34
|
+
}
|
35
|
+
|
36
|
+
let(:processor_2) {
|
37
|
+
Class.new {
|
38
|
+
include Substation::Processor::Pivot
|
39
|
+
def call(request)
|
40
|
+
request.success(:success_2)
|
41
|
+
end
|
42
|
+
}.new(processor_2_name, handler, processor_config)
|
43
|
+
}
|
44
|
+
|
45
|
+
let(:processor_3) {
|
46
|
+
Class.new {
|
47
|
+
include Substation::Processor::Outgoing
|
48
|
+
def call(response)
|
49
|
+
respond_with(response, :success_3)
|
50
|
+
end
|
51
|
+
}.new(processor_3_name, handler, processor_config)
|
52
|
+
}
|
53
|
+
|
54
|
+
let(:response) { Response::Success.new(current_request, :success_3) }
|
55
|
+
let(:current_request) { Request.new(name, env, :success_1) }
|
56
|
+
|
57
|
+
it { should eql(response) }
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when an incoming processor is not successful' do
|
61
|
+
|
62
|
+
let(:processor_2) {
|
63
|
+
Class.new {
|
64
|
+
include Substation::Processor::Pivot
|
65
|
+
def call(request)
|
66
|
+
request.success(:success_1)
|
67
|
+
end
|
68
|
+
}.new(processor_2_name, handler, processor_config)
|
69
|
+
}
|
70
|
+
|
71
|
+
let(:processor_3) {
|
72
|
+
Class.new {
|
73
|
+
include Substation::Processor::Outgoing
|
74
|
+
def call(response)
|
75
|
+
respond_with(response, :success_3)
|
76
|
+
end
|
77
|
+
}.new(processor_3_name, handler, processor_config)
|
78
|
+
}
|
79
|
+
|
80
|
+
let(:response_class) { Response::Failure }
|
81
|
+
|
82
|
+
context 'because it returned a failure response' do
|
83
|
+
let(:processor_1) {
|
84
|
+
Class.new {
|
85
|
+
include Substation::Processor::Incoming
|
86
|
+
def call(request)
|
87
|
+
request.error(:error_1)
|
88
|
+
end
|
89
|
+
}.new(processor_1_name, handler, processor_config)
|
90
|
+
}
|
91
|
+
|
92
|
+
let(:response) { Response::Failure.new(request, :error_1) }
|
93
|
+
|
94
|
+
it { should eql(response) }
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'because it raised an uncaught exception' do
|
98
|
+
let(:processor_1) {
|
99
|
+
Class.new {
|
100
|
+
include Substation::Processor::Incoming
|
101
|
+
def call(request)
|
102
|
+
raise RuntimeError, 'exception_1'
|
103
|
+
end
|
104
|
+
}.new(processor_1_name, handler, processor_config)
|
105
|
+
}
|
106
|
+
|
107
|
+
let(:response) { Response::Exception.new(request, data) }
|
108
|
+
let(:data) { Response::Exception::Output.new(input, RuntimeError.new('exception_1')) }
|
109
|
+
|
110
|
+
it { should eql(response) }
|
111
|
+
|
112
|
+
it 'wraps the original exception instance' do
|
113
|
+
expect(subject.output.exception.message).to eql('exception_1')
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'calls the failure chain' do
|
117
|
+
expect(exception_chain).to receive(:call).with(response)
|
118
|
+
subject
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'when the pivot processor is not successful' do
|
124
|
+
let(:processor_1) {
|
125
|
+
Class.new {
|
126
|
+
include Substation::Processor::Incoming
|
127
|
+
def call(request)
|
128
|
+
request.success(:success_1)
|
129
|
+
end
|
130
|
+
}.new(processor_1_name, handler, processor_config)
|
131
|
+
}
|
132
|
+
|
133
|
+
let(:processor_3) {
|
134
|
+
Class.new {
|
135
|
+
include Substation::Processor::Outgoing
|
136
|
+
def call(response)
|
137
|
+
response
|
138
|
+
end
|
139
|
+
}.new(processor_3_name, handler, processor_config)
|
140
|
+
}
|
141
|
+
|
142
|
+
let(:response_class) { Response::Failure }
|
143
|
+
|
144
|
+
context 'because it returned a failure response' do
|
145
|
+
let(:processor_2) {
|
146
|
+
Class.new {
|
147
|
+
include Substation::Processor::Pivot
|
148
|
+
def call(request)
|
149
|
+
request.error(:error_2)
|
150
|
+
end
|
151
|
+
}.new(processor_2_name, handler, processor_config)
|
152
|
+
}
|
153
|
+
|
154
|
+
let(:response) { Response::Failure.new(current_request, :error_2) }
|
155
|
+
let(:current_request) { Request.new(name, env, :success_1) }
|
156
|
+
|
157
|
+
it { should eql(response) }
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'because it raised an uncaught exception' do
|
161
|
+
let(:processor_2) {
|
162
|
+
Class.new {
|
163
|
+
include Substation::Processor::Pivot
|
164
|
+
def call(request)
|
165
|
+
raise RuntimeError, 'exception_2'
|
166
|
+
end
|
167
|
+
}.new(processor_2_name, handler, processor_config)
|
168
|
+
}
|
169
|
+
|
170
|
+
let(:response) { Response::Exception.new(request.to_request(:success_1), data) }
|
171
|
+
let(:data) { Response::Exception::Output.new(:success_1, RuntimeError.new('exception_2')) }
|
172
|
+
let(:current_request) { Request.new(name, env, :success_1) }
|
173
|
+
|
174
|
+
it { should eql(response) }
|
175
|
+
|
176
|
+
it 'wraps the original exception instance' do
|
177
|
+
expect(subject.output.exception.message).to eql('exception_2')
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'calls the failure chain' do
|
181
|
+
expect(exception_chain).to receive(:call).with(response)
|
182
|
+
subject
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
context 'when an outgoing processor is not successful' do
|
188
|
+
let(:processor_1) {
|
189
|
+
Class.new {
|
190
|
+
include Substation::Processor::Incoming
|
191
|
+
def call(request)
|
192
|
+
request.success(:success_1)
|
193
|
+
end
|
194
|
+
}.new(processor_1_name, handler, processor_config)
|
195
|
+
}
|
196
|
+
|
197
|
+
let(:processor_2) {
|
198
|
+
Class.new {
|
199
|
+
include Substation::Processor::Pivot
|
200
|
+
def call(response)
|
201
|
+
response.success(:success_2)
|
202
|
+
end
|
203
|
+
}.new(processor_2_name, handler, processor_config)
|
204
|
+
}
|
205
|
+
|
206
|
+
let(:response_class) { Response::Failure }
|
207
|
+
|
208
|
+
context 'because it raised an uncaught exception' do
|
209
|
+
let(:processor_3) {
|
210
|
+
Class.new {
|
211
|
+
include Substation::Processor::Outgoing
|
212
|
+
def call(response)
|
213
|
+
raise RuntimeError, 'exception_3'
|
214
|
+
end
|
215
|
+
}.new(processor_3_name, handler, processor_config)
|
216
|
+
}
|
217
|
+
|
218
|
+
let(:response) { Response::Exception.new(request.to_request(:success_2), data) }
|
219
|
+
let(:data) { Response::Exception::Output.new(:success_2, RuntimeError.new('exception_3')) }
|
220
|
+
let(:current_request) { Request.new(name, env, :success_1) }
|
221
|
+
let(:current_response) { Response::Success.new(current_request, :success_2) }
|
222
|
+
|
223
|
+
it { should eql(response) }
|
224
|
+
|
225
|
+
it 'wraps the original exception instance' do
|
226
|
+
expect(subject.output.exception.message).to eql('exception_3')
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'calls the failure chain' do
|
230
|
+
expect(exception_chain).to receive(:call).with(response)
|
231
|
+
subject
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
describe '#each' do
|
238
|
+
subject { object.each { |tuple| yields << processor } }
|
239
|
+
|
240
|
+
let(:object) { described_class.new(processors, described_class::EMPTY) }
|
241
|
+
let(:processors) { [ processor ] }
|
242
|
+
let(:processor) { Spec::FAKE_PROCESSOR }
|
243
|
+
let(:yields) { [] }
|
244
|
+
|
245
|
+
before do
|
246
|
+
expect(object).to be_instance_of(described_class)
|
247
|
+
end
|
248
|
+
|
249
|
+
it_should_behave_like 'an #each method'
|
250
|
+
|
251
|
+
it 'yields only processors' do
|
252
|
+
subject
|
253
|
+
yields.each { |processor| expect(processor).to be_instance_of(Spec::Processor) }
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'yields only processors with the expected handler' do
|
257
|
+
expect { subject }.to change { yields.dup }
|
258
|
+
.from([])
|
259
|
+
.to([ processor ])
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe Chain do
|
264
|
+
subject { described_class.new(processors, described_class::EMPTY) }
|
265
|
+
|
266
|
+
let(:processors) { [ processor ] }
|
267
|
+
let(:processor) { Spec::FAKE_PROCESSOR }
|
268
|
+
|
269
|
+
before do
|
270
|
+
expect(subject).to be_instance_of(described_class)
|
271
|
+
end
|
272
|
+
|
273
|
+
it { should be_kind_of(Enumerable) }
|
274
|
+
end
|
275
|
+
|
276
|
+
describe '.exception_response' do
|
277
|
+
subject { described_class.exception_response(state, data, exception) }
|
278
|
+
|
279
|
+
include_context 'Request#initialize'
|
280
|
+
|
281
|
+
let(:data) { double('data') }
|
282
|
+
let(:exception) { double('exception') }
|
283
|
+
let(:exception_data) { Response::Exception::Output.new(data, exception) }
|
284
|
+
|
285
|
+
let(:expected) { Response::Exception.new(expected_request, exception_data) }
|
286
|
+
|
287
|
+
context 'when a request is passed as current state' do
|
288
|
+
let(:state) { request }
|
289
|
+
let(:expected_request) { request.to_request(data) }
|
290
|
+
|
291
|
+
it { should eql(expected) }
|
292
|
+
end
|
293
|
+
|
294
|
+
context 'when a response is passed as current state' do
|
295
|
+
let(:state) { response }
|
296
|
+
let(:expected_request) { response.to_request(data) }
|
297
|
+
let(:response) { Response::Failure.new(request, output) }
|
298
|
+
let(:output) { double('output') }
|
299
|
+
|
300
|
+
it { should eql(expected) }
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Dispatcher do
|
6
|
+
describe '#call' do
|
7
|
+
|
8
|
+
subject { object.call(name, input) }
|
9
|
+
|
10
|
+
include_context 'Request#initialize'
|
11
|
+
|
12
|
+
let(:object) { described_class.new(config, env) }
|
13
|
+
let(:config) { DSL::Registry.new(guard, :test => Spec::Action::Success) }
|
14
|
+
let(:guard) { double('guard') }
|
15
|
+
|
16
|
+
let(:expected_response) do
|
17
|
+
Spec::Action::Success.call(request)
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'when the action is registered' do
|
21
|
+
let(:name) { :test }
|
22
|
+
|
23
|
+
it { should eql(expected_response) }
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when the action is not registered' do
|
27
|
+
let(:name) { :unknown }
|
28
|
+
|
29
|
+
specify do
|
30
|
+
expect { subject }.to raise_error(described_class::UnknownActionError)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.new_registry' do
|
36
|
+
subject { described_class.new_registry }
|
37
|
+
|
38
|
+
let(:expected) { DSL::Registry.new(described_class::GUARD) }
|
39
|
+
|
40
|
+
it { should eql(expected) }
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#include?' do
|
44
|
+
|
45
|
+
subject { object.include?(name) }
|
46
|
+
|
47
|
+
let(:object) { described_class.new(actions, env) }
|
48
|
+
let(:actions) { Hash[action => double('action')] }
|
49
|
+
let(:action) { double('action') }
|
50
|
+
let(:env) { double('env') }
|
51
|
+
|
52
|
+
context 'when the action is registered' do
|
53
|
+
let(:name) { action }
|
54
|
+
|
55
|
+
it 'returns true' do
|
56
|
+
expect(subject).to be(true)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when the action is not registered' do
|
61
|
+
let(:name) { :unknown }
|
62
|
+
|
63
|
+
it 'returns false' do
|
64
|
+
expect(subject).to be(false)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe DSL::Guard do
|
6
|
+
describe '#call' do
|
7
|
+
subject { object.call(name, registry) }
|
8
|
+
|
9
|
+
let(:name) { double('name') }
|
10
|
+
let(:registry) { double('registry') }
|
11
|
+
|
12
|
+
context 'when no reserved names are given' do
|
13
|
+
let(:object) { described_class.new }
|
14
|
+
|
15
|
+
context 'when the given name is valid' do
|
16
|
+
let(:name) { :test }
|
17
|
+
|
18
|
+
before do
|
19
|
+
expect(registry).to receive(:include?).with(name).and_return(false)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'raises no error' do
|
23
|
+
expect { subject }.to_not raise_error
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when the given name is already registered' do
|
28
|
+
let(:name) { :test }
|
29
|
+
let(:msg) { described_class::ALREADY_REGISTERED_MSG % name.inspect }
|
30
|
+
|
31
|
+
before do
|
32
|
+
expect(registry).to receive(:include?).with(name).and_return(true)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'raises ReservedNameError' do
|
36
|
+
expect { subject }.to raise_error(AlreadyRegisteredError, msg)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when reserved names are given' do
|
42
|
+
let(:object) { described_class.new(reserved_names) }
|
43
|
+
let(:reserved_names) { double('reserved_names') }
|
44
|
+
|
45
|
+
before do
|
46
|
+
expect(registry).to receive(:include?).with(name).and_return(false)
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when the given name is not reserved' do
|
50
|
+
before do
|
51
|
+
expect(reserved_names).to receive(:include?).with(name).and_return(false)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'raises no error' do
|
55
|
+
expect { subject }.to_not raise_error
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when the given name is reserved' do
|
60
|
+
let(:msg) { described_class::RESERVED_NAME_MSG % name.inspect }
|
61
|
+
|
62
|
+
before do
|
63
|
+
expect(reserved_names).to receive(:include?).with(name).and_return(true)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'raises ReservedNameError' do
|
67
|
+
expect { subject }.to raise_error(ReservedNameError, msg)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe DSL::Registry do
|
6
|
+
describe '#each' do
|
7
|
+
subject { object.each(&block) }
|
8
|
+
|
9
|
+
let(:object) { described_class.new(guard, entries) }
|
10
|
+
let(:guard) { double('guard') }
|
11
|
+
let(:entries) { { name => entry } }
|
12
|
+
let(:name) { double('name') }
|
13
|
+
let(:entry) { double('entry') }
|
14
|
+
let(:block) { ->(_) { } }
|
15
|
+
|
16
|
+
it_should_behave_like 'an #each method'
|
17
|
+
|
18
|
+
it { should be_kind_of(Enumerable) }
|
19
|
+
|
20
|
+
it 'yields all entries' do
|
21
|
+
expect { |block| object.each(&block) }.to yield_successive_args([name, entry])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#[]=' do
|
26
|
+
subject { object[name] = expected }
|
27
|
+
|
28
|
+
let(:object) { described_class.new(guard) }
|
29
|
+
let(:guard) { DSL::Guard.new(reserved_names) }
|
30
|
+
let(:reserved_names) { EMPTY_ARRAY }
|
31
|
+
let(:expected) { double('expected') }
|
32
|
+
let(:name) { double('name', :to_sym => coerced_name) }
|
33
|
+
let(:coerced_name) { double('coerced_name') }
|
34
|
+
|
35
|
+
context 'when name is not yet registered' do
|
36
|
+
it 'returns registered object' do
|
37
|
+
should be(expected)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'registers given object' do
|
41
|
+
subject
|
42
|
+
expect(object.fetch(name)).to be(expected)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when name is already registered' do
|
47
|
+
let(:msg) { DSL::Guard::ALREADY_REGISTERED_MSG % coerced_name.inspect }
|
48
|
+
|
49
|
+
before { object[name] = expected }
|
50
|
+
|
51
|
+
specify { expect { subject }.to raise_error(AlreadyRegisteredError, msg) }
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'when name is reserved' do
|
55
|
+
let(:msg) { DSL::Guard::RESERVED_NAME_MSG % coerced_name.inspect }
|
56
|
+
let(:reserved_names) { [coerced_name] }
|
57
|
+
|
58
|
+
specify { expect { subject }.to raise_error(ReservedNameError, msg) }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#fetch' do
|
63
|
+
|
64
|
+
let(:object) { described_class.new(guard, entries) }
|
65
|
+
let(:guard) { double('guard') }
|
66
|
+
let(:name) { double('name') }
|
67
|
+
let(:coerced_name) { double('coerced_name') }
|
68
|
+
|
69
|
+
before do
|
70
|
+
expect(name).to receive(:to_sym).and_return(coerced_name)
|
71
|
+
end
|
72
|
+
|
73
|
+
context 'when name is not yet registered' do
|
74
|
+
let(:entries) { {} }
|
75
|
+
|
76
|
+
context 'and a block is given' do
|
77
|
+
subject { object.fetch(name, &block) }
|
78
|
+
|
79
|
+
let(:block) { ->(_) { block_return } }
|
80
|
+
let(:block_return) { double('block_return') }
|
81
|
+
|
82
|
+
it { should be(block_return) }
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'and no block is given' do
|
86
|
+
subject { object.fetch(name) }
|
87
|
+
|
88
|
+
it 'should behave like Hash#fetch' do
|
89
|
+
expect { subject }.to raise_error(KeyError)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'when name is already registered' do
|
95
|
+
subject { object.fetch(name) }
|
96
|
+
|
97
|
+
let(:entries) { { coerced_name => expected } }
|
98
|
+
let(:expected) { double('expected') }
|
99
|
+
|
100
|
+
it { should be(expected) }
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '#include?' do
|
105
|
+
subject { object.include?(name) }
|
106
|
+
|
107
|
+
let(:object) { described_class.new(guard, entries) }
|
108
|
+
let(:guard) { double('guard') }
|
109
|
+
let(:name) { double('name') }
|
110
|
+
let(:coerced_name) { double('coerced_name') }
|
111
|
+
|
112
|
+
before do
|
113
|
+
expect(name).to receive(:to_sym).with(no_args).and_return(coerced_name)
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'when name is included' do
|
117
|
+
let(:entries) { { coerced_name => data } }
|
118
|
+
let(:data) { double('data') }
|
119
|
+
|
120
|
+
it { should be(true) }
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'when name is not included' do
|
124
|
+
let(:entries) { {} }
|
125
|
+
|
126
|
+
it { should be(false) }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe '#keys' do
|
131
|
+
subject { object.keys }
|
132
|
+
|
133
|
+
let(:object) { described_class.new(guard, entries) }
|
134
|
+
let(:guard) { double('guard') }
|
135
|
+
let(:entries) { { key => value } }
|
136
|
+
let(:key) { double('key') }
|
137
|
+
let(:value) { double('value') }
|
138
|
+
|
139
|
+
it { should eql([key]) }
|
140
|
+
end
|
141
|
+
|
142
|
+
describe '#merge' do
|
143
|
+
subject { object.merge(other) }
|
144
|
+
|
145
|
+
let(:other) { described_class.new(guard, entries) }
|
146
|
+
let(:entries) { { coerced_name => data } }
|
147
|
+
let(:data) { double('data') }
|
148
|
+
|
149
|
+
let(:guard) { double('guard') }
|
150
|
+
let(:name) { double('name') }
|
151
|
+
let(:coerced_name) { double('coerced_name') }
|
152
|
+
|
153
|
+
before do
|
154
|
+
expect(coerced_name).to receive(:to_sym).with(no_args).and_return(coerced_name)
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'when other contains equally named objects' do
|
158
|
+
before do
|
159
|
+
expect(guard).to receive(:call).with(coerced_name, entries).and_raise(RuntimeError)
|
160
|
+
end
|
161
|
+
|
162
|
+
let(:object) { described_class.new(guard, entries) }
|
163
|
+
|
164
|
+
it 'raises an error' do
|
165
|
+
expect { subject }.to raise_error(RuntimeError)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'when other only contains new names as keys' do
|
170
|
+
before do
|
171
|
+
expect(guard).to receive(:call).with(coerced_name, {})
|
172
|
+
end
|
173
|
+
|
174
|
+
let(:object) { described_class.new(guard) }
|
175
|
+
let(:expected) { described_class.new(guard, entries) }
|
176
|
+
|
177
|
+
it { should eql(expected) }
|
178
|
+
it { should_not be(object) }
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|