pipeline 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), '..', 'spec_helper')
1
+ require 'spec/spec_helper'
2
2
 
3
3
  module Pipeline
4
4
  describe ApiMethods do
@@ -48,6 +48,7 @@ module Pipeline
48
48
  describe "#resume" do
49
49
  before(:each) do
50
50
  @pipeline = Pipeline::Base.new
51
+ @pipeline.stub!(:resume)
51
52
  Pipeline::Base.stub!(:find).with('1').and_return(@pipeline)
52
53
  Delayed::Job.stub!(:enqueue)
53
54
  end
@@ -72,10 +73,10 @@ module Pipeline
72
73
  Pipeline.resume('1')
73
74
  end
74
75
 
75
- it "should raise error is trying to resume in invalid state" do
76
- @pipeline.send(:_setup)
76
+ it "should resume pipeline instance" do
77
+ @pipeline.should_receive(:resume)
77
78
 
78
- lambda {Pipeline.resume('1')}.should raise_error(InvalidStatusError, "Status is already in progress")
79
+ Pipeline.resume('1')
79
80
  end
80
81
 
81
82
  end
@@ -1,53 +1,9 @@
1
- require File.join(File.dirname(__FILE__), '..', 'spec_helper')
2
-
3
- class FirstStage < Pipeline::Stage::Base
4
- def run
5
- @executed = true
6
- end
7
-
8
- def executed?
9
- !!@executed
10
- end
11
- end
12
-
13
- class SecondStage < FirstStage; end # Ugly.. just so I don't have to write stub again
14
-
15
- class IrrecoverableStage < FirstStage
16
- def run
17
- super
18
- raise Pipeline::IrrecoverableError.new
19
- end
20
- end
21
-
22
- class RecoverableInputRequiredStage < FirstStage
23
- def run
24
- super
25
- raise Pipeline::RecoverableError.new("message", true)
26
- end
27
- end
28
-
29
- class RecoverableStage < FirstStage
30
- def run
31
- super
32
- raise Pipeline::RecoverableError.new("message")
33
- end
34
- end
35
-
36
- class GenericErrorStage < FirstStage
37
- def run
38
- super
39
- raise Exception.new
40
- end
41
- end
42
-
43
- class SamplePipeline < Pipeline::Base
44
- define_stages FirstStage >> SecondStage
45
- end
1
+ require 'spec/spec_helper'
46
2
 
47
3
  module Pipeline
48
4
  describe Base do
49
5
 
50
- describe "- configuring" do
6
+ context "- configuring" do
51
7
  before(:each) do
52
8
  class ::SamplePipeline
53
9
  define_stages FirstStage >> SecondStage
@@ -70,7 +26,7 @@ module Pipeline
70
26
  end
71
27
  end
72
28
 
73
- describe "- setup" do
29
+ context "- setup" do
74
30
  before(:each) do
75
31
  @pipeline = SamplePipeline.new
76
32
  end
@@ -88,15 +44,15 @@ module Pipeline
88
44
  end
89
45
  end
90
46
 
91
- describe "- persistence" do
47
+ context "- persistence" do
92
48
  before(:each) do
93
49
  @pipeline = Base.new
94
50
  end
95
51
 
96
52
  it "should persist pipeline instance" do
97
- @pipeline.id.should be_nil
53
+ @pipeline.should be_new_record
98
54
  lambda {@pipeline.save!}.should_not raise_error
99
- @pipeline.id.should_not be_nil
55
+ @pipeline.should_not be_new_record
100
56
  end
101
57
 
102
58
  it "should allow retrieval by id" do
@@ -149,20 +105,15 @@ module Pipeline
149
105
  end
150
106
  end
151
107
 
152
- describe "- execution (success)" do
108
+ context "- execution (success)" do
153
109
  before(:each) do
154
- class ::SamplePipeline
155
- define_stages FirstStage >> SecondStage
156
- end
157
- @pipeline = ::SamplePipeline.new
110
+ @pipeline = SamplePipeline.new
158
111
  end
159
112
 
160
113
  it "should increment attempts" do
161
- pipeline = SamplePipeline.new
162
-
163
- pipeline.attempts.should == 0
164
- pipeline.perform
165
- pipeline.attempts.should == 1
114
+ @pipeline.attempts.should == 0
115
+ @pipeline.perform
116
+ @pipeline.attempts.should == 1
166
117
  end
167
118
 
168
119
  it "should perform each stage" do
@@ -183,7 +134,7 @@ module Pipeline
183
134
  end
184
135
  end
185
136
 
186
- describe "- execution (in progress)" do
137
+ context "- execution (in progress)" do
187
138
  it "should set status to in_progress" do
188
139
  pipeline = SamplePipeline.new
189
140
  pipeline.send(:_setup)
@@ -193,7 +144,7 @@ module Pipeline
193
144
  end
194
145
  end
195
146
 
196
- describe "- execution (irrecoverable error)" do
147
+ context "- execution (irrecoverable error)" do
197
148
  before(:each) do
198
149
  class ::SamplePipeline
199
150
  define_stages FirstStage >> IrrecoverableStage
@@ -217,7 +168,7 @@ module Pipeline
217
168
  end
218
169
  end
219
170
 
220
- describe "- execution (recoverable error that doesn't require user input)" do
171
+ context "- execution (recoverable error that doesn't require user input)" do
221
172
  before(:each) do
222
173
  class ::SamplePipeline
223
174
  define_stages FirstStage >> RecoverableStage
@@ -241,7 +192,7 @@ module Pipeline
241
192
  end
242
193
  end
243
194
 
244
- describe "- execution (recoverable error that requires user input)" do
195
+ context "- execution (recoverable error that requires user input)" do
245
196
  before(:each) do
246
197
  class ::SamplePipeline
247
198
  define_stages FirstStage >> RecoverableInputRequiredStage
@@ -265,7 +216,7 @@ module Pipeline
265
216
  end
266
217
  end
267
218
 
268
- describe "- execution (other errors will use failure mode to pause/cancel pipeline)" do
219
+ context "- execution (other errors will use failure mode to pause/cancel pipeline)" do
269
220
  before(:each) do
270
221
  class ::SamplePipeline
271
222
  define_stages FirstStage >> GenericErrorStage
@@ -304,7 +255,7 @@ module Pipeline
304
255
  end
305
256
  end
306
257
 
307
- describe "- execution (retrying)" do
258
+ context "- execution (retrying)" do
308
259
  before(:each) do
309
260
  class ::SamplePipeline
310
261
  define_stages FirstStage >> RecoverableInputRequiredStage
@@ -344,15 +295,14 @@ module Pipeline
344
295
 
345
296
  # Status gets updated to failed on the database (not on the current instance)
346
297
  same_pipeline = SamplePipeline.find(@pipeline.id)
347
- same_pipeline.send(:status=, :failed)
348
- same_pipeline.save!
298
+ same_pipeline.update_attribute(:status, :failed)
349
299
 
350
300
  # Retrying should fail because pipeline is now failed
351
301
  lambda {@pipeline.perform}.should raise_error(InvalidStatusError, "Status is already failed")
352
302
  end
353
303
  end
354
304
 
355
- describe "- execution (state transitions)" do
305
+ context "- execution (state transitions)" do
356
306
  before(:each) do
357
307
  @pipeline = Base.new
358
308
  end
@@ -363,42 +313,42 @@ module Pipeline
363
313
  end
364
314
 
365
315
  it "should execute if status is :paused (for retrying)" do
366
- @pipeline.send(:status=, :paused)
316
+ @pipeline.update_attribute(:status, :paused)
367
317
 
368
318
  @pipeline.should be_ok_to_resume
369
319
  lambda {@pipeline.perform}.should_not raise_error(InvalidStatusError)
370
320
  end
371
321
 
372
322
  it "should execute if status is :retry" do
373
- @pipeline.send(:status=, :retry)
323
+ @pipeline.update_attribute(:status, :retry)
374
324
 
375
325
  @pipeline.should be_ok_to_resume
376
326
  lambda {@pipeline.perform}.should_not raise_error(InvalidStatusError)
377
327
  end
378
328
 
379
329
  it "should not execute if status is :in_progress" do
380
- @pipeline.send(:status=, :in_progress)
330
+ @pipeline.update_attribute(:status, :in_progress)
381
331
 
382
332
  @pipeline.should_not be_ok_to_resume
383
333
  lambda {@pipeline.perform}.should raise_error(InvalidStatusError, "Status is already in progress")
384
334
  end
385
335
 
386
336
  it "should not execute if status is :completed" do
387
- @pipeline.send(:status=, :completed)
337
+ @pipeline.update_attribute(:status, :completed)
388
338
 
389
339
  @pipeline.should_not be_ok_to_resume
390
340
  lambda {@pipeline.perform}.should raise_error(InvalidStatusError, "Status is already completed")
391
341
  end
392
342
 
393
343
  it "should not execute if status is :failed" do
394
- @pipeline.send(:status=, :failed)
344
+ @pipeline.update_attribute(:status, :failed)
395
345
 
396
346
  @pipeline.should_not be_ok_to_resume
397
347
  lambda {@pipeline.perform}.should raise_error(InvalidStatusError, "Status is already failed")
398
348
  end
399
349
  end
400
350
 
401
- describe "- cancelling" do
351
+ context "- cancelling" do
402
352
  before(:each) do
403
353
  class ::SamplePipeline
404
354
  define_stages FirstStage >> RecoverableInputRequiredStage
@@ -417,9 +367,22 @@ module Pipeline
417
367
  @pipeline.cancel
418
368
  @pipeline.reload.status.should == :failed
419
369
  end
370
+
371
+ it "should refresh object (in case it was updated after job was scheduled)" do
372
+ # Gets paused on the first time
373
+ @pipeline.save!
374
+
375
+ # Status gets updated to failed on the database (not on the current instance)
376
+ same_pipeline = SamplePipeline.find(@pipeline.id)
377
+ same_pipeline.update_attribute(:status, :failed)
378
+
379
+ # Retrying should fail because pipeline is now failed
380
+ lambda {@pipeline.cancel}.should raise_error(InvalidStatusError, "Status is already failed")
381
+ end
382
+
420
383
  end
421
384
 
422
- describe "- cancelling (state transitions)" do
385
+ context "- cancelling (state transitions)" do
423
386
  before(:each) do
424
387
  @pipeline = Base.new
425
388
  end
@@ -429,29 +392,105 @@ module Pipeline
429
392
  end
430
393
 
431
394
  it "should cancel if status is :paused (for retrying)" do
432
- @pipeline.send(:status=, :paused)
395
+ @pipeline.update_attribute(:status, :paused)
433
396
 
434
397
  lambda {@pipeline.cancel}.should_not raise_error(InvalidStatusError)
435
398
  end
436
399
 
437
400
  it "should not cancel if status is :in_progress" do
438
- @pipeline.send(:status=, :in_progress)
401
+ @pipeline.update_attribute(:status, :in_progress)
439
402
 
440
403
  lambda {@pipeline.cancel}.should raise_error(InvalidStatusError, "Status is already in progress")
441
404
  end
442
405
 
443
406
  it "should not cancel if status is :completed" do
444
- @pipeline.send(:status=, :completed)
407
+ @pipeline.update_attribute(:status, :completed)
445
408
 
446
409
  lambda {@pipeline.cancel}.should raise_error(InvalidStatusError, "Status is already completed")
447
410
  end
448
411
 
449
412
  it "should not cancel if status is :failed" do
450
- @pipeline.send(:status=, :failed)
413
+ @pipeline.update_attribute(:status, :failed)
451
414
 
452
415
  lambda {@pipeline.cancel}.should raise_error(InvalidStatusError, "Status is already failed")
453
416
  end
454
417
  end
418
+
419
+ context "- resuming" do
420
+ before(:each) do
421
+ class ::SamplePipeline
422
+ define_stages FirstStage >> RecoverableInputRequiredStage
423
+ end
424
+ @pipeline = SamplePipeline.new
425
+ @pipeline.perform
426
+ end
427
+
428
+ it "should refresh object (in case it was updated after job was scheduled)" do
429
+ # Gets paused on the first time
430
+ @pipeline.save!
431
+
432
+ # Status gets updated to failed on the database (not on the current instance)
433
+ same_pipeline = SamplePipeline.find(@pipeline.id)
434
+ same_pipeline.update_attribute(:status, :failed)
435
+
436
+ # Retrying should fail because pipeline is now failed
437
+ lambda {@pipeline.resume}.should raise_error(InvalidStatusError, "Status is already failed")
438
+ end
439
+ end
455
440
 
441
+ context "- resuming (state transitions)" do
442
+ before(:each) do
443
+ @pipeline = Base.new
444
+ end
445
+
446
+ it "should resume if status is :not_started" do
447
+ lambda {@pipeline.resume}.should_not raise_error(InvalidStatusError)
448
+ end
449
+
450
+ it "should resume if status is :paused (for retrying)" do
451
+ @pipeline.update_attribute(:status, :paused)
452
+
453
+ lambda {@pipeline.resume}.should_not raise_error(InvalidStatusError)
454
+ end
455
+
456
+ it "should not resume if status is :in_progress" do
457
+ @pipeline.update_attribute(:status, :in_progress)
458
+
459
+ lambda {@pipeline.resume}.should raise_error(InvalidStatusError, "Status is already in progress")
460
+ end
461
+
462
+ it "should not resume if status is :completed" do
463
+ @pipeline.update_attribute(:status, :completed)
464
+
465
+ lambda {@pipeline.resume}.should raise_error(InvalidStatusError, "Status is already completed")
466
+ end
467
+
468
+ it "should not resume if status is :failed" do
469
+ @pipeline.update_attribute(:status, :failed)
470
+
471
+ lambda {@pipeline.resume}.should raise_error(InvalidStatusError, "Status is already failed")
472
+ end
473
+ end
474
+
475
+ context "- callbacks" do
476
+ before(:each) do
477
+ @pipeline = ::SamplePipeline.new
478
+ end
479
+
480
+ it "should allow callback before running the pipeline" do
481
+ @pipeline.should_receive(:before_pipeline_callback).once
482
+ @pipeline.perform
483
+ end
484
+
485
+ it "should allow callback after running the pipeline" do
486
+ @pipeline.should_receive(:after_pipeline_callback).once
487
+ @pipeline.perform
488
+ end
489
+
490
+ it "should run callback after cancelling a pipeline" do
491
+ @pipeline.should_receive(:after_pipeline_callback).once
492
+ @pipeline.cancel
493
+ end
494
+ end
456
495
  end
457
496
  end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
1
+ require 'spec/spec_helper'
2
2
 
3
3
  # Reusing stage table to simplify database integration tests
4
4
  class FakeForSymbolAttribute < ActiveRecord::Base
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
1
+ require 'spec/spec_helper'
2
2
 
3
3
  # Reusing stage table to simplify database integration tests
4
4
  class FakeForTransactionalAttribute < ActiveRecord::Base
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
1
+ require 'spec/spec_helper'
2
2
 
3
3
  module Pipeline
4
4
  describe InvalidPipelineError do
@@ -1,20 +1,10 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
2
-
3
- class SampleStage < Pipeline::Stage::Base
4
- def run
5
- @executed = true
6
- end
7
-
8
- def executed?
9
- !!@executed
10
- end
11
- end
1
+ require 'spec/spec_helper'
12
2
 
13
3
  module Pipeline
14
4
  module Stage
15
5
  describe Base do
16
6
 
17
- describe "- chaining" do
7
+ context "- chaining" do
18
8
  class Step1 < Base; end
19
9
  class Step2 < Base; end
20
10
  class Step3 < Base; end
@@ -32,23 +22,23 @@ module Pipeline
32
22
  end
33
23
  end
34
24
 
35
- describe "- setup" do
25
+ context "- setup" do
36
26
  it "should set default name" do
37
27
  Base.new.name.should == "Pipeline::Stage::Base"
38
- SampleStage.new.name.should == "SampleStage"
28
+ ::SampleStage.new.name.should == "SampleStage"
39
29
  end
40
30
 
41
31
  it "should allow overriding name at class level" do
42
- SampleStage.default_name = "My custom stage name"
43
- SampleStage.new.name.should == "My custom stage name"
32
+ StubStage.default_name = "My custom stage name"
33
+ StubStage.new.name.should == "My custom stage name"
44
34
 
45
- SampleStage.default_name = :some_symbol
46
- SampleStage.new.name.should == "some_symbol"
35
+ StubStage.default_name = :some_symbol
36
+ StubStage.new.name.should == "some_symbol"
47
37
  end
48
38
 
49
39
  it "should allow specifying a name on creation" do
50
40
  Base.new(:name => "My Name").name.should == "My Name"
51
- SampleStage.new(:name => "Customized Name").name.should == "Customized Name"
41
+ StubStage.new(:name => "Customized Name").name.should == "Customized Name"
52
42
  end
53
43
 
54
44
  it "should start with status not_started" do
@@ -57,24 +47,28 @@ module Pipeline
57
47
 
58
48
  it "should validate status" do
59
49
  lambda {Base.new(:status => :something_else)}.should raise_error
50
+ end
51
+
52
+ it "should raise error if subclass doesn't implement #run" do
53
+ lambda {Base.new.run}.should raise_error("This method must be implemented by any subclass of Pipeline::Stage::Base")
60
54
  end
61
55
  end
62
56
 
63
- describe "- persistence" do
57
+ context "- persistence" do
64
58
  before(:each) do
65
- @stage = SampleStage.new
59
+ @stage = StubStage.new
66
60
  end
67
61
 
68
62
  it "should persist stage" do
69
- @stage.id.should be_nil
63
+ @stage.should be_new_record
70
64
  lambda {@stage.save!}.should_not raise_error
71
- @stage.id.should_not be_nil
65
+ @stage.should_not be_new_record
72
66
  end
73
67
 
74
68
  it "should allow retrieval by id" do
75
69
  @stage.save!
76
70
 
77
- s = SampleStage.find(@stage.id)
71
+ s = StubStage.find(@stage.id)
78
72
  s.should === @stage
79
73
 
80
74
  lambda {Base.find('invalid_id')}.should raise_error(ActiveRecord::RecordNotFound)
@@ -83,7 +77,7 @@ module Pipeline
83
77
  it "should persist type as single table inheritance" do
84
78
  @stage.save!
85
79
  stage = Base.find(@stage.id)
86
- stage.should be_an_instance_of(SampleStage)
80
+ stage.should be_an_instance_of(StubStage)
87
81
  end
88
82
 
89
83
  it "should belong to pipeline instance" do
@@ -96,9 +90,9 @@ module Pipeline
96
90
 
97
91
  end
98
92
 
99
- describe "- execution (success)" do
93
+ context "- execution (success)" do
100
94
  before(:each) do
101
- @stage = SampleStage.new
95
+ @stage = StubStage.new
102
96
  end
103
97
 
104
98
  it "should update status after finished" do
@@ -128,89 +122,90 @@ module Pipeline
128
122
 
129
123
  end
130
124
 
131
- describe "- execution (failure)" do
132
- before(:each) do
133
- @stage = SampleStage.new
134
- @stage.stub!(:run).and_raise(StandardError.new)
135
- end
136
-
125
+ context "- execution (failure)" do
137
126
  it "should re-raise error" do
138
- lambda {@stage.perform}.should raise_error
127
+ stage = FailedStage.new
128
+ lambda {stage.perform}.should raise_error
139
129
  end
140
130
 
141
131
  it "should update status on irrecoverable error" do
142
- @stage.should_receive(:run).and_raise(IrrecoverableError.new)
143
- lambda {@stage.perform}.should raise_error(IrrecoverableError)
144
- @stage.status.should == :failed
145
- @stage.reload.status.should == :failed
132
+ stage = IrrecoverableStage.new
133
+ lambda {stage.perform}.should raise_error(IrrecoverableError)
134
+ stage.status.should == :failed
135
+ stage.reload.status.should == :failed
146
136
  end
147
137
 
148
138
  it "should update message on irrecoverable error" do
149
- @stage.should_receive(:run).and_raise(IrrecoverableError.new("message"))
150
- lambda {@stage.perform}.should raise_error(IrrecoverableError)
151
- @stage.message.should == "message"
152
- @stage.reload.message.should == "message"
139
+ stage = IrrecoverableStage.new
140
+ lambda {stage.perform}.should raise_error(IrrecoverableError)
141
+ stage.message.should == "message"
142
+ stage.reload.message.should == "message"
153
143
  end
154
144
 
155
145
  it "should update status on recoverable error (not requiring input)" do
156
- @stage.should_receive(:run).and_raise(RecoverableError.new)
157
- lambda {@stage.perform}.should raise_error(RecoverableError)
158
- @stage.status.should == :failed
159
- @stage.reload.status.should == :failed
146
+ stage = RecoverableStage.new
147
+ lambda {stage.perform}.should raise_error(RecoverableError)
148
+ stage.status.should == :failed
149
+ stage.reload.status.should == :failed
160
150
  end
161
151
 
162
152
  it "should update status on recoverable error (requiring input)" do
163
- @stage.should_receive(:run).and_raise(RecoverableError.new("message", true))
164
- lambda {@stage.perform}.should raise_error(RecoverableError)
165
- @stage.status.should == :failed
166
- @stage.reload.status.should == :failed
153
+ stage = RecoverableInputRequiredStage.new
154
+ lambda {stage.perform}.should raise_error(RecoverableError)
155
+ stage.status.should == :failed
156
+ stage.reload.status.should == :failed
167
157
  end
168
158
 
169
159
  it "should update message on recoverable error" do
170
- @stage.should_receive(:run).and_raise(RecoverableError.new("message"))
171
- lambda {@stage.perform}.should raise_error(RecoverableError)
172
- @stage.message.should == "message"
173
- @stage.reload.message.should == "message"
160
+ stage = RecoverableStage.new
161
+ lambda {stage.perform}.should raise_error(RecoverableError)
162
+ stage.message.should == "message"
163
+ stage.reload.message.should == "message"
174
164
  end
175
165
 
176
166
  it "should capture generic Exception" do
177
- @stage.should_receive(:run).and_raise(Exception.new)
178
- lambda {@stage.perform}.should raise_error(Exception)
179
- @stage.status.should == :failed
180
- @stage.reload.status.should == :failed
167
+ stage = GenericErrorStage.new
168
+ lambda {stage.perform}.should raise_error(Exception)
169
+ stage.status.should == :failed
170
+ stage.reload.status.should == :failed
181
171
  end
182
172
 
183
173
  it "should log exception message and backtrace" do
184
- SampleStage.default_name = "SampleStage"
185
- error = StandardError.new("error message")
186
- error.set_backtrace(['a', 'b', 'c'])
187
- @stage.should_receive(:run).and_raise(error)
174
+ class StageFailWithDetails < StubStage
175
+ self.default_name = "Fail With Details"
176
+
177
+ def run
178
+ super
179
+ error = StandardError.new("error message")
180
+ error.set_backtrace(['a', 'b', 'c'])
181
+ raise error
182
+ end
183
+ end
184
+ stage = StageFailWithDetails.new
188
185
 
189
- @stage.logger.should_receive(:info).with("Error on stage SampleStage: error message")
190
- @stage.logger.should_receive(:info).with("a\nb\nc")
191
- lambda {@stage.perform}.should raise_error
186
+ stage.logger.should_receive(:info).with("Error on stage Fail With Details: error message")
187
+ stage.logger.should_receive(:info).with("a\nb\nc")
188
+ lambda {stage.perform}.should raise_error
192
189
  end
193
190
 
194
191
  it "should refresh object (in case it was cancelled after job was scheduled)" do
195
192
  # Gets failed on the first time
196
- @stage.save!
197
- @stage.should_receive(:run).and_raise(RecoverableError.new("message"))
198
- lambda {@stage.perform}.should raise_error(RecoverableError)
193
+ stage = RecoverableStage.create!
194
+ lambda {stage.perform}.should raise_error(RecoverableError)
199
195
 
200
196
  # Status gets updated to completed on the database (not on the current instance)
201
- same_stage = SampleStage.find(@stage.id)
202
- same_stage.send(:status=, :completed)
203
- same_stage.save!
197
+ same_stage = StubStage.find(stage.id)
198
+ same_stage.update_attribute(:status, :completed)
204
199
 
205
200
  # Retrying should fail because stage is now completed
206
- lambda {@stage.perform}.should raise_error(InvalidStatusError, "Status is already completed")
201
+ lambda {stage.perform}.should raise_error(InvalidStatusError, "Status is already completed")
207
202
  end
208
203
 
209
204
  end
210
205
 
211
- describe "- execution (in progress)" do
206
+ context "- execution (in progress)" do
212
207
  it "should set status to in_progress" do
213
- stage = SampleStage.new
208
+ stage = StubStage.new
214
209
  stage.send(:_setup)
215
210
 
216
211
  stage.status.should == :in_progress
@@ -218,7 +213,7 @@ module Pipeline
218
213
  end
219
214
 
220
215
  it "should clear message when restarting" do
221
- stage = SampleStage.new(:message => 'some message')
216
+ stage = StubStage.new(:message => 'some message')
222
217
  stage.send(:_setup)
223
218
 
224
219
  stage.message.should be_nil
@@ -226,35 +221,55 @@ module Pipeline
226
221
  end
227
222
  end
228
223
 
229
- describe "- execution (state transitions)" do
224
+ context "- execution (state transitions)" do
225
+ before(:each) do
226
+ @stage = StubStage.new
227
+ end
228
+
230
229
  it "should execute if status is :not_started" do
231
- stage = SampleStage.new
232
-
233
- lambda {stage.perform}.should_not raise_error(InvalidStatusError)
230
+ lambda {@stage.perform}.should_not raise_error(InvalidStatusError)
234
231
  end
235
232
 
236
233
  it "should execute if status is :failed (for retrying)" do
237
- stage = SampleStage.new
238
- stage.send(:status=, :failed)
234
+ @stage.update_attribute(:status, :failed)
239
235
 
240
- lambda {stage.perform}.should_not raise_error(InvalidStatusError)
236
+ lambda {@stage.perform}.should_not raise_error(InvalidStatusError)
241
237
  end
242
238
 
243
239
  it "should not execute if status is :in_progress" do
244
- stage = SampleStage.new
245
- stage.send(:status=, :in_progress)
240
+ @stage.update_attribute(:status, :in_progress)
246
241
 
247
- lambda {stage.perform}.should raise_error(InvalidStatusError, "Status is already in progress")
242
+ lambda {@stage.perform}.should raise_error(InvalidStatusError, "Status is already in progress")
248
243
  end
249
244
 
250
245
  it "should not execute if status is :completed" do
251
- stage = SampleStage.new
252
- stage.send(:status=, :completed)
246
+ @stage.update_attribute(:status, :completed)
253
247
 
254
- lambda {stage.perform}.should raise_error(InvalidStatusError, "Status is already completed")
248
+ lambda {@stage.perform}.should raise_error(InvalidStatusError, "Status is already completed")
255
249
  end
256
250
  end
257
251
 
252
+ context "- callbacks" do
253
+ before(:each) do
254
+ @stage = ::SampleStage.new
255
+ end
256
+
257
+ it "should allow callback before running the stage" do
258
+ @stage.should_receive(:before_stage_callback).once
259
+ @stage.perform
260
+ end
261
+
262
+ it "should allow callback after running the stage on success" do
263
+ @stage.should_receive(:after_stage_callback).once
264
+ @stage.perform
265
+ end
266
+
267
+ it "should allow callback after running the stage on failure" do
268
+ @stage.stub!(:run).and_raise("error")
269
+ @stage.should_receive(:after_stage_callback).once
270
+ lambda {@stage.perform}.should raise_error
271
+ end
272
+ end
258
273
  end
259
274
  end
260
275
  end