step_machine 0.0.3

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,80 @@
1
+ module StepMachine
2
+
3
+ class Step
4
+
5
+ attr_accessor :name, :block, :next_step, :group, :exception
6
+ attr_reader :result, :validation, :condition_block
7
+
8
+ def initialize(name)
9
+ self.name = name
10
+ end
11
+
12
+ def validate(value = nil, &block)
13
+ @validation = block || value
14
+ self
15
+ end
16
+
17
+ def errors(init_error = nil)
18
+ @errors = init_error if (!init_error.nil? and init_error.class != @errors.class)
19
+ @errors = [] if (init_error.nil? && @errors.nil?)
20
+ @errors
21
+ end
22
+
23
+ def success(&block)
24
+ @success = block
25
+ self
26
+ end
27
+
28
+ def next_step(&block)
29
+ @next_step = block if block
30
+ @next_step
31
+ end
32
+
33
+ def condition(&block)
34
+ @condition_block = block if block
35
+ self
36
+ end
37
+
38
+ def next
39
+ return next_step.call(self) if next_step.is_a?(Proc)
40
+ next_step
41
+ end
42
+
43
+ def perform
44
+ return true unless condition_satisfied
45
+ @performed = true
46
+ @result = block.call(self)
47
+ valid = valid?
48
+ @success.call(self) if @success && valid
49
+ valid
50
+ rescue => e
51
+ @exception = e
52
+ false
53
+ end
54
+
55
+ def performed?
56
+ !!@performed
57
+ end
58
+
59
+ private
60
+
61
+ def valid?
62
+ if validation
63
+ return (!(validation.call(self) === false) && errors.empty?) if validation.is_a?(Proc)
64
+ return false unless errors.empty?
65
+ return result.match(validation) if validation.is_a?(Regexp)
66
+ return validation == result
67
+ end
68
+ true
69
+ end
70
+
71
+ def condition_satisfied
72
+ return false if (group && group.condition_block && !group.condition_block.call)
73
+ return false if (condition_block && !condition_block.call)
74
+ true
75
+ end
76
+
77
+
78
+ end
79
+
80
+ end
@@ -0,0 +1,3 @@
1
+ module StepMachine
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,585 @@
1
+ require "spec_helper"
2
+
3
+ describe StepMachine::Runner do
4
+
5
+ before :each do
6
+ @runner = StepMachine::Runner.new
7
+ end
8
+
9
+ describe 'on group' do
10
+
11
+ it "should create and return the group" do
12
+ group = @runner.group(:group)
13
+
14
+ group.should be_a(StepMachine::Group)
15
+ group.name.should == :group
16
+ end
17
+
18
+ it "should return an existing group" do
19
+ group = @runner.group(:group)
20
+
21
+ expect(@runner.group(:group)).to eql(group)
22
+ end
23
+
24
+ it "should assign the first step defined as first step of group" do
25
+ @runner.group(:group_1) do
26
+ @runner.step(:step_1) {}
27
+ @runner.step(:step_2) {}
28
+ end
29
+
30
+ @runner.group(:group_1).first_step.should == @runner.step(:step_1)
31
+ end
32
+
33
+ it "should create an step with the surrounding group" do
34
+ @runner.group(:group_1) do
35
+ @runner.step(:step_1) {}
36
+ end
37
+
38
+ @runner.group(:group_2) do
39
+ @runner.step(:step_2) {}
40
+ end
41
+
42
+ @runner.step(:step_3) {}
43
+
44
+ @runner.step(:step_1).group.name.should == :group_1
45
+ @runner.step(:step_2).group.name.should == :group_2
46
+ @runner.step(:step_3).group.should be_nil
47
+ end
48
+
49
+ it "should assign a condition with group" do
50
+ block = proc {x + 1}
51
+ @runner.group(:group_1) do
52
+ @runner.step(:step_2) {}
53
+ end.condition &block
54
+ expect(@runner.group(:group_1).condition_block).to eql(block)
55
+ end
56
+
57
+ end
58
+
59
+ describe "on step" do
60
+
61
+ it "should create an step with the given name and block" do
62
+
63
+ block = proc { x + 1 }
64
+ step = @runner.step(:name, &block)
65
+
66
+ step.name.should == :name
67
+ step.block.should == block
68
+ end
69
+
70
+ it "should return the required step" do
71
+ step_1 = @runner.step(:step_1) {}
72
+ step_2 = @runner.step(:step_2) {}
73
+
74
+ @runner.step(:step_1).should == step_1
75
+ end
76
+
77
+ it "should update the step with the last given block" do
78
+ block = proc { x + 1 }
79
+
80
+ @runner.step(:step_1) {}
81
+ @runner.step(:step_1, &block)
82
+
83
+ @runner.step(:step_1).block.should == block
84
+ end
85
+
86
+ it "should assign the next step automatically" do
87
+ step_1 = @runner.step(:step_1) {}
88
+ step_2 = @runner.step(:step_2) {}
89
+
90
+ step_1.next_step.should == step_2
91
+ end
92
+
93
+ it "should assign the first step automatically" do
94
+ step_1 = @runner.step(:step_1) {}
95
+ @runner.first_step.should == step_1
96
+
97
+ step_2 = @runner.step(:step_2) {}
98
+ @runner.first_step.should == step_1
99
+ end
100
+ end
101
+
102
+ describe "on run" do
103
+ it "should run the given step" do
104
+ @runner.step(:step) { 1 + 1}
105
+
106
+ @runner.run
107
+
108
+ @runner.step(:step).result.should == 2
109
+ end
110
+
111
+ it "should run the steps based in the steps order" do
112
+ x = 0
113
+
114
+ @runner.step(:step_1) { x += 1 }
115
+ @runner.step(:step_2) { x += 1 }
116
+
117
+ @runner.run
118
+
119
+ x.should == 2
120
+ end
121
+
122
+ it "should run the steps correctly wne the order is changed" do
123
+ order = []
124
+
125
+ block = proc { |s| order << s.name }
126
+
127
+ @runner.step(:step_1, &block)
128
+ @runner.step(:step_2, &block)
129
+ @runner.step(:step_3, &block)
130
+
131
+ @runner.step(:step_1).next_step = @runner.step(:step_3)
132
+ @runner.step(:step_3).next_step = @runner.step(:step_2)
133
+ @runner.step(:step_2).next_step = nil
134
+
135
+ @runner.run
136
+
137
+ order.should == [:step_1, :step_3, :step_2]
138
+ end
139
+
140
+ it "should run the steps correctly wne the order is changed" do
141
+ order = []
142
+
143
+ block = proc { |s| order << s.name }
144
+
145
+ @runner.step(:step_1, &block)
146
+ @runner.step(:step_2, &block)
147
+ @runner.step(:step_3, &block)
148
+
149
+ @runner.step(:step_1).next_step = @runner.step(:step_3)
150
+ @runner.step(:step_3).next_step { @runner.step(:step_2) }
151
+ @runner.step(:step_2).next_step = nil
152
+
153
+ @runner.run
154
+
155
+ order.should == [:step_1, :step_3, :step_2]
156
+ end
157
+
158
+ it "should start on the given first step" do
159
+ order = []
160
+
161
+ block = proc { |s| order << s.name }
162
+
163
+ @runner.step(:step_1, &block)
164
+ @runner.step(:step_2, &block)
165
+ @runner.step(:step_3, &block)
166
+
167
+ @runner.step(:step_1).next_step = @runner.step(:step_3)
168
+ @runner.step(:step_3).next_step { @runner.step(:step_2) }
169
+ @runner.step(:step_2).next_step = nil
170
+
171
+ @runner.first_step = @runner.step(:step_2)
172
+
173
+ @runner.run
174
+
175
+ order.should == [:step_2]
176
+ end
177
+
178
+ it "should stop execution if a step fail" do
179
+ order = []
180
+
181
+ block = proc { |s| order << s.name }
182
+
183
+ @runner.step(:step_1, &block)
184
+ @runner.step(:step_2, &block)
185
+ @runner.step(:step_3, &block).validate { false }
186
+
187
+ @runner.step(:step_1).next_step = @runner.step(:step_3)
188
+ @runner.step(:step_3).next_step { @runner.step(:step_2) }
189
+ @runner.step(:step_2).next_step = nil
190
+
191
+ @runner.run
192
+
193
+ order.should == [:step_1, :step_3]
194
+ end
195
+
196
+
197
+ it "should store the failed step" do
198
+ @runner.step(:step_1) {}
199
+ @runner.step(:step_2) {}
200
+ @runner.step(:step_3) {}.validate { false }
201
+
202
+ @runner.step(:step_1).next_step = @runner.step(:step_3)
203
+ @runner.step(:step_3).next_step { @runner.step(:step_2) }
204
+ @runner.step(:step_2).next_step = nil
205
+
206
+ @runner.run
207
+
208
+ @runner.failed_step.should == @runner.step(:step_3)
209
+ end
210
+
211
+ it "should run only the steps of the given group" do
212
+ order = []
213
+
214
+ block = proc { |s| order << s.name }
215
+
216
+ @runner.group :group do
217
+ @runner.step(:step_1, &block)
218
+ @runner.step(:step_2, &block)
219
+ end
220
+ @runner.step(:step_3, &block)
221
+
222
+ @runner.run( :group => :group )
223
+
224
+ order.should == [:step_1, :step_2]
225
+ end
226
+
227
+ it "should run the steps up to given step" do
228
+ order = []
229
+ block = proc { |s| order << s.name }
230
+ @runner.step(:step_1, &block)
231
+ @runner.step(:step_2, &block)
232
+ @runner.step(:step_3, &block)
233
+ @runner.run( :upto => :step_2 )
234
+ order.should == [:step_1, :step_2]
235
+ end
236
+
237
+ it "should run the steps from given step" do
238
+ order = []
239
+ block = proc { |s| order << s.name }
240
+ @runner.step(:step_1, &block)
241
+ @runner.step(:step_2, &block)
242
+ @runner.step(:step_3, &block)
243
+ @runner.run( :from => :step_2 )
244
+ order.should == [:step_2, :step_3]
245
+ end
246
+
247
+ it "should run the steps from step_2 upto step_3" do
248
+ order = []
249
+ block = proc { |s| order << s.name }
250
+ @runner.step(:step_1, &block)
251
+ @runner.step(:step_2, &block)
252
+ @runner.step(:step_3, &block)
253
+ @runner.step(:step_4, &block)
254
+ @runner.run( :from => :step_2, :upto => :step_3 )
255
+ order.should == [:step_2, :step_3]
256
+ end
257
+
258
+ it "should evaluate the group condition" do
259
+ order = []
260
+ block = proc { |s| order << s.name }
261
+
262
+ @runner.step(:step_1, &block)
263
+
264
+ @runner.group :group do
265
+ @runner.step(:step_2, &block)
266
+ @runner.step(:step_3, &block)
267
+ end.condition { false }
268
+
269
+ @runner.step(:step_4, &block)
270
+
271
+ @runner.run
272
+
273
+ expect(order).to eql([:step_1, :step_4])
274
+ end
275
+
276
+ end
277
+
278
+ describe "on_step_failure" do
279
+
280
+ it "it should execute the given block if the step fails" do
281
+ @runner.step(:step_1){ }.validate{false}
282
+
283
+ x = 0
284
+ @runner.on_step_failure{x += 1}
285
+
286
+ @runner.run
287
+
288
+ x.should == 1
289
+ end
290
+
291
+ it "it should execute more than one blocks if the step fails" do
292
+ @runner.step(:step_1){ }.validate{false}
293
+
294
+ x = 0
295
+ @runner.on_step_failure{x += 1}
296
+ @runner.on_step_failure{x += 2}
297
+
298
+ @runner.run
299
+
300
+ x.should == 3
301
+ end
302
+
303
+ it "should pass the failed step to the block" do
304
+ step_1 = @runner.step(:step_1){ }.validate{false}
305
+
306
+ x = 0
307
+ @runner.on_step_failure do |f|
308
+ f.step.should == step_1
309
+ end
310
+
311
+ @runner.run
312
+ end
313
+
314
+ it "should execute the on step failure block only on the given steps" do
315
+ @runner.step(:step_1) {}.validate {false}
316
+ @runner.step(:step_2) {}.validate {false}
317
+
318
+ step_failed = nil
319
+ @runner.on_step_failure :only => [:step_1] {|f| step_failed = f.step.name}
320
+ @runner.run
321
+ step_failed.should == :step_1
322
+
323
+ @runner.first_step = step(:step_2)
324
+ step_failed = nil
325
+ @runner.run
326
+ step_failed.should == nil
327
+ end
328
+
329
+ it "should execute the on step failure block excluding on the given steps" do
330
+ @runner.step(:step_1) {}.validate {false}
331
+ @runner.step(:step_2) {}.validate {false}
332
+
333
+ step_failed = nil
334
+ @runner.on_step_failure :except => [:step_2] {|f| step_failed = f.step.name}
335
+ @runner.run
336
+ step_failed.should == :step_1
337
+
338
+ @runner.first_step = step(:step_2)
339
+ step_failed = nil
340
+ @runner.run
341
+ step_failed.should == nil
342
+ end
343
+
344
+ it "should go to the specified step" do
345
+ order = []
346
+
347
+ block = proc {|s| order << s.name}
348
+
349
+ @runner.step(:step_1, &block).validate {false}
350
+ @runner.step(:step_2, &block)
351
+
352
+ @runner.on_step_failure do |treatment|
353
+ treatment.go_to :step_2
354
+ end
355
+
356
+ @runner.run
357
+
358
+ order.should == [:step_1, :step_2]
359
+ @runner.status.should == :success
360
+ end
361
+
362
+ it "should repeat the failed step" do
363
+ order = []
364
+ count = 0
365
+
366
+ block = proc {|s| order << s.name}
367
+
368
+ @runner.step(:step_1, &block).validate {false}
369
+ @runner.step(:step_2, &block)
370
+
371
+ @runner.on_step_failure do |f|
372
+ f.repeat if count == 0
373
+ count += 1
374
+ end
375
+
376
+ @runner.run
377
+
378
+ order.should == [:step_1, :step_1]
379
+ @runner.status.should == :failure
380
+ end
381
+
382
+ it "should ignore the failure and continue" do
383
+ order = []
384
+
385
+ block = proc {|s| order << s.name}
386
+
387
+ @runner.step(:step_1, &block).validate {false}
388
+ @runner.step(:step_2, &block)
389
+
390
+ @runner.on_step_failure do |f|
391
+ f.continue
392
+ end
393
+
394
+ @runner.run
395
+
396
+ order.should == [:step_1, :step_2]
397
+ @runner.status.should == :success
398
+ end
399
+
400
+
401
+ it "should restart the process" do
402
+ order = []
403
+ count = 0
404
+
405
+ block = proc {|s| order << s.name}
406
+
407
+ @runner.step(:step_1, &block)
408
+ @runner.step(:step_2, &block).validate do |s|
409
+ count += 1
410
+ count > 1
411
+ end
412
+ @runner.step(:step_3, &block)
413
+
414
+ @runner.on_step_failure do |f|
415
+ f.restart
416
+ end
417
+
418
+ @runner.run
419
+
420
+ order.should == [:step_1, :step_2, :step_1, :step_2, :step_3]
421
+ @runner.status.should == :success
422
+ end
423
+
424
+ it "should restart the process 2 times" do
425
+ order = []
426
+
427
+ block = proc {|s| order << s.name}
428
+
429
+ @runner.step(:step_1, &block)
430
+ @runner.step(:step_2, &block).validate { false }
431
+ @runner.step(:step_3, &block)
432
+
433
+ @runner.on_step_failure do |f|
434
+ f.restart.times(2)
435
+ end
436
+
437
+ @runner.run
438
+
439
+ order.should == [:step_1, :step_2, :step_1, :step_2, :step_1, :step_2]
440
+ @runner.times_to_repeat.should == -1
441
+ @runner.status.should == :failure
442
+ end
443
+
444
+ it "should repeat step 2 times" do
445
+ order = []
446
+
447
+ block = proc {|s| order << s.name}
448
+
449
+ @runner.step(:step_1, &block)
450
+ @runner.step(:step_2, &block).validate { false }
451
+ @runner.step(:step_3, &block)
452
+
453
+ @runner.on_step_failure do |f|
454
+ f.repeat.times(2)
455
+ end
456
+
457
+ @runner.run
458
+
459
+ order.should == [:step_1, :step_2, :step_2, :step_2]
460
+ @runner.times_to_repeat.should == -1
461
+ @runner.status.should == :failure
462
+ end
463
+
464
+ it "it should execute failure when has errors message on step" do
465
+ @runner.step(:step_1_errors){x=1}.validate {|step| step.errors << 'errors' }
466
+ x = 0
467
+ @runner.on_step_failure{x += 1}
468
+ @runner.on_step_failure{x += 2}
469
+
470
+ @runner.run
471
+
472
+ x.should == 3
473
+ end
474
+
475
+ it "it should execute success when hasn't errors message on step" do
476
+ @runner.step(:step_1_not_failed){x=1}.validate {}
477
+ x = 0
478
+ @runner.on_step_failure{x += 1}
479
+ @runner.on_step_failure{x += 2}
480
+
481
+ @runner.run
482
+
483
+ x.should == 0
484
+ end
485
+
486
+ end
487
+
488
+ describe "before each step" do
489
+ it "should execute the block given" do
490
+ executed = []
491
+
492
+ @runner.step(:step_1) {}
493
+ @runner.step(:step_2) {}
494
+
495
+ @runner.before_each_step {|s| executed << s.name}
496
+ @runner.run
497
+
498
+ executed.should == [:step_1, :step_2]
499
+ end
500
+
501
+ it "should execute the block given only in the given steps" do
502
+ executed = []
503
+
504
+ @runner.step(:step_1) {}
505
+ @runner.step(:step_2) {}
506
+
507
+ @runner.before_each_step :only => [:step_2] {|s| executed << s.name}
508
+ @runner.run
509
+
510
+ executed.should == [:step_2]
511
+ end
512
+
513
+ it "should execute the block given except in the given steps" do
514
+ executed = []
515
+
516
+ @runner.step(:step_1) {}
517
+ @runner.step(:step_2) {}
518
+
519
+ @runner.before_each_step :except => [:step_2] {|s| executed << s.name}
520
+ @runner.run
521
+
522
+ executed.should == [:step_1]
523
+ end
524
+ end
525
+
526
+ describe "after each step" do
527
+ it "should execute the block given" do
528
+ executed = []
529
+
530
+ @runner.step(:step_1) {}
531
+ @runner.step(:step_2) {}
532
+
533
+ @runner.after_each_step {|s| executed << s.name}
534
+ @runner.run
535
+
536
+ executed.should == [:step_1, :step_2]
537
+ end
538
+
539
+ it "should execute the block given only in the given steps" do
540
+ executed = []
541
+
542
+ @runner.step(:step_1) {}
543
+ @runner.step(:step_2) {}
544
+
545
+ @runner.after_each_step :only => [:step_2] {|s| executed << s.name}
546
+ @runner.run
547
+
548
+ executed.should == [:step_2]
549
+ end
550
+
551
+ it "should execute the block given except in the given steps" do
552
+ executed = []
553
+
554
+ @runner.step(:step_1) {}
555
+ @runner.step(:step_2) {}
556
+
557
+ @runner.after_each_step :except => [:step_2] {|s| executed << s.name}
558
+ @runner.run
559
+
560
+ executed.should == [:step_1]
561
+ end
562
+ end
563
+
564
+ describe "result status" do
565
+
566
+ it "should be success if all steps were performed" do
567
+ @runner.step(:step_1) {}
568
+ @runner.step(:step_2) {}
569
+
570
+ @runner.run
571
+
572
+ @runner.status.should == :success
573
+ end
574
+
575
+ it "should be failure if all steps were performed" do
576
+ @runner.step(:step_1) {}
577
+ @runner.step(:step_2) {}.validate {false}
578
+
579
+ @runner.run
580
+
581
+ @runner.status.should == :failure
582
+ end
583
+
584
+ end
585
+ end