seam-active_record 1.0.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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +45 -0
  6. data/Rakefile +1 -0
  7. data/lib/seam/active_record/version.rb +5 -0
  8. data/lib/seam/active_record.rb +75 -0
  9. data/lib/seam_effort.rb +3 -0
  10. data/migration_script.rb +13 -0
  11. data/seam-mongodb.gemspec +32 -0
  12. data/test_app/.gitignore +16 -0
  13. data/test_app/Gemfile +45 -0
  14. data/test_app/README.rdoc +28 -0
  15. data/test_app/Rakefile +6 -0
  16. data/test_app/app/assets/images/.keep +0 -0
  17. data/test_app/app/assets/javascripts/application.js +16 -0
  18. data/test_app/app/assets/stylesheets/application.css +15 -0
  19. data/test_app/app/controllers/application_controller.rb +5 -0
  20. data/test_app/app/controllers/concerns/.keep +0 -0
  21. data/test_app/app/helpers/application_helper.rb +2 -0
  22. data/test_app/app/mailers/.keep +0 -0
  23. data/test_app/app/models/.keep +0 -0
  24. data/test_app/app/models/concerns/.keep +0 -0
  25. data/test_app/app/views/layouts/application.html.erb +14 -0
  26. data/test_app/bin/bundle +3 -0
  27. data/test_app/bin/rails +8 -0
  28. data/test_app/bin/rake +8 -0
  29. data/test_app/bin/spring +18 -0
  30. data/test_app/config/application.rb +23 -0
  31. data/test_app/config/boot.rb +4 -0
  32. data/test_app/config/database.yml +25 -0
  33. data/test_app/config/environment.rb +5 -0
  34. data/test_app/config/environments/development.rb +37 -0
  35. data/test_app/config/environments/production.rb +82 -0
  36. data/test_app/config/environments/test.rb +39 -0
  37. data/test_app/config/initializers/assets.rb +8 -0
  38. data/test_app/config/initializers/backtrace_silencers.rb +7 -0
  39. data/test_app/config/initializers/cookies_serializer.rb +3 -0
  40. data/test_app/config/initializers/filter_parameter_logging.rb +4 -0
  41. data/test_app/config/initializers/inflections.rb +16 -0
  42. data/test_app/config/initializers/mime_types.rb +4 -0
  43. data/test_app/config/initializers/session_store.rb +3 -0
  44. data/test_app/config/initializers/wrap_parameters.rb +14 -0
  45. data/test_app/config/locales/en.yml +23 -0
  46. data/test_app/config/routes.rb +56 -0
  47. data/test_app/config/secrets.yml +22 -0
  48. data/test_app/config.ru +4 -0
  49. data/test_app/db/migrate/20140904165307_create_seam_efforts.rb +13 -0
  50. data/test_app/db/schema.rb +26 -0
  51. data/test_app/db/seeds.rb +7 -0
  52. data/test_app/lib/assets/.keep +0 -0
  53. data/test_app/lib/tasks/.keep +0 -0
  54. data/test_app/log/.keep +0 -0
  55. data/test_app/public/404.html +67 -0
  56. data/test_app/public/422.html +67 -0
  57. data/test_app/public/500.html +66 -0
  58. data/test_app/public/favicon.ico +0 -0
  59. data/test_app/public/robots.txt +5 -0
  60. data/test_app/spec/seam/effort_spec.rb +43 -0
  61. data/test_app/spec/seam/flow_spec.rb +173 -0
  62. data/test_app/spec/seam/persistence_spec.rb +0 -0
  63. data/test_app/spec/seam/step_spec.rb +34 -0
  64. data/test_app/spec/seam/wait_worker_spec.rb +179 -0
  65. data/test_app/spec/seam/worker_spec.rb +910 -0
  66. data/test_app/spec/seam_spec.rb +47 -0
  67. data/test_app/spec/spec_helper.rb +13 -0
  68. data/test_app/vendor/assets/javascripts/.keep +0 -0
  69. data/test_app/vendor/assets/stylesheets/.keep +0 -0
  70. metadata +252 -0
@@ -0,0 +1,910 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "worker" do
4
+
5
+ before do
6
+ Seam::Persistence.destroy
7
+ @stamp_data_history = true
8
+ end
9
+
10
+ after do
11
+ Timecop.return
12
+ end
13
+
14
+ describe "step" do
15
+ it "should match the name" do
16
+ worker = Seam::Worker.new
17
+ worker.handles(:darren)
18
+ worker.step.must_equal "darren"
19
+ end
20
+ end
21
+
22
+ describe "move_to_next_step" do
23
+
24
+ [:date].to_objects {[
25
+ ['1/1/2011'],
26
+ ['3/4/2015']
27
+ ]}.each do |test|
28
+
29
+ describe "move immediately" do
30
+
31
+ before { Timecop.freeze Time.parse(test.date) }
32
+ after { Timecop.return }
33
+
34
+ it "should move to the next step and set the date to now" do
35
+ flow = Seam::Flow.new
36
+ flow.apple
37
+ flow.orange
38
+
39
+ effort = flow.start( { first_name: 'John' } )
40
+ effort = Seam::Effort.find(effort.id)
41
+
42
+ effort.next_step.must_equal "apple"
43
+
44
+ apple_worker = Seam::Worker.new
45
+ apple_worker.handles(:apple)
46
+ def apple_worker.process
47
+ move_to_next_step
48
+ end
49
+
50
+ apple_worker.execute effort
51
+
52
+ effort = Seam::Effort.find(effort.id)
53
+ effort.next_step.must_equal "orange"
54
+ effort.next_execute_at.must_equal Time.parse(test.date)
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+
61
+ [:date, :next_date].to_objects {[
62
+ ['1/1/2011', '2/1/2011'],
63
+ ['1/1/2011', '2/2/2011'],
64
+ ['3/4/2015', '4/5/2016']
65
+ ]}.each do |test|
66
+
67
+ describe "move to some point in the future" do
68
+
69
+ before { Timecop.freeze Time.parse(test.date) }
70
+ after { Timecop.return }
71
+
72
+ it "should move to the next step and set the date to now" do
73
+ flow = Seam::Flow.new
74
+ flow.apple
75
+ flow.orange
76
+
77
+ effort = flow.start( { first_name: 'John' } )
78
+ effort = Seam::Effort.find(effort.id)
79
+
80
+ effort.next_step.must_equal "apple"
81
+
82
+ apple_worker = Seam::Worker.new
83
+ apple_worker.handles(:apple)
84
+ eval("
85
+ def apple_worker.process
86
+ move_to_next_step( { on: Time.parse('#{test.next_date}') } )
87
+ end
88
+ ")
89
+
90
+ apple_worker.execute effort
91
+
92
+ effort = Seam::Effort.find(effort.id)
93
+ effort.next_step.must_equal "orange"
94
+ effort.next_execute_at.must_equal Time.parse(test.next_date)
95
+ end
96
+
97
+ end
98
+
99
+ end
100
+ end
101
+
102
+ describe "move_to_next_step as a default" do
103
+ it "should go to move_to_next_step by default" do
104
+ flow = Seam::Flow.new
105
+ flow.apple
106
+ flow.orange
107
+
108
+ effort = flow.start( { first_name: 'John' } )
109
+ effort = Seam::Effort.find(effort.id)
110
+
111
+ effort.next_step.must_equal "apple"
112
+
113
+ apple_worker = Seam::Worker.new
114
+ apple_worker.handles(:apple)
115
+ def apple_worker.process
116
+ end
117
+
118
+ apple_worker.execute effort
119
+
120
+ effort = Seam::Effort.find(effort.id)
121
+ effort.next_step.must_equal "orange"
122
+ end
123
+ end
124
+
125
+ describe "try_again_in" do
126
+
127
+ let(:effort) do
128
+ flow = Seam::Flow.new
129
+ flow.apple
130
+ flow.orange
131
+
132
+ e = flow.start( { first_name: 'John' } )
133
+ Seam::Effort.find(e.id)
134
+ end
135
+
136
+ before do
137
+ Timecop.freeze Time.parse('3/4/2013')
138
+ effort.next_step.must_equal "apple"
139
+
140
+ apple_worker = Seam::Worker.new
141
+ apple_worker.handles(:apple)
142
+ def apple_worker.process
143
+ try_again_in 1.day
144
+ end
145
+
146
+ apple_worker.execute effort
147
+ end
148
+
149
+ it "should not update the next step" do
150
+ fresh_effort = Seam::Effort.find(effort.id)
151
+ fresh_effort.next_step.must_equal "apple"
152
+ end
153
+
154
+ it "should update the next execute date" do
155
+ fresh_effort = Seam::Effort.find(effort.id)
156
+ fresh_effort.next_execute_at.must_equal Time.parse('4/4/2013')
157
+ end
158
+ end
159
+
160
+ describe "try_again_on" do
161
+
162
+ describe "putting it off for one day" do
163
+ let(:effort) do
164
+ flow = Seam::Flow.new
165
+ flow.apple
166
+ flow.orange
167
+
168
+ e = flow.start( { first_name: 'John' } )
169
+ Seam::Effort.find(e.id)
170
+ end
171
+
172
+ before do
173
+ Timecop.freeze Time.parse('3/4/2013')
174
+ effort.next_step.must_equal "apple"
175
+
176
+ apple_worker = Seam::Worker.new
177
+ apple_worker.handles(:apple)
178
+ def apple_worker.process
179
+ try_again_on Time.parse('4/4/2013')
180
+ end
181
+
182
+ apple_worker.execute effort
183
+ end
184
+
185
+ it "should not update the next step" do
186
+ fresh_effort = Seam::Effort.find(effort.id)
187
+ fresh_effort.next_step.must_equal "apple"
188
+ end
189
+
190
+ it "should update the next execute date" do
191
+ fresh_effort = Seam::Effort.find(effort.id)
192
+ fresh_effort.next_execute_at.must_equal Time.parse('4/4/2013')
193
+ end
194
+
195
+ it "should update the history" do
196
+ fresh_effort = Seam::Effort.find(effort.id)
197
+ fresh_effort.history[0]['try_again_on'].must_equal Time.parse('4/4/2013')
198
+ end
199
+ end
200
+ end
201
+
202
+ describe "more copmlex example" do
203
+
204
+ let(:effort1) do
205
+ flow = Seam::Flow.new
206
+ flow.grape
207
+ flow.mango
208
+
209
+ e = flow.start( { status: 'Good' } )
210
+ Seam::Effort.find(e.id)
211
+ end
212
+
213
+ let(:effort2) do
214
+ flow = Seam::Flow.new
215
+ flow.grape
216
+ flow.mango
217
+
218
+ e = flow.start( { status: 'Bad' } )
219
+ Seam::Effort.find(e.id)
220
+ end
221
+
222
+ before do
223
+ Timecop.freeze Time.parse('1/6/2013')
224
+
225
+ apple_worker = Seam::Worker.new
226
+ apple_worker.handles(:apple)
227
+ def apple_worker.process
228
+ if @current_effort.data[:status] == 'Good'
229
+ move_to_next_step
230
+ else
231
+ try_again_in 1.day
232
+ end
233
+ end
234
+
235
+ apple_worker.execute effort1
236
+ apple_worker.execute effort2
237
+ end
238
+
239
+ it "should move the first effort forward" do
240
+ fresh_effort = Seam::Effort.find(effort1.id)
241
+ fresh_effort.next_step.must_equal "mango"
242
+ end
243
+
244
+ it "should keep the second effort at the same step" do
245
+ fresh_effort = Seam::Effort.find(effort2.id)
246
+ fresh_effort.next_step.must_equal "grape"
247
+ fresh_effort.next_execute_at.must_equal Time.parse('2/6/2013')
248
+ end
249
+ end
250
+
251
+ describe "processing all pending steps for one effort" do
252
+ let(:effort1_creator) do
253
+ ->() do
254
+ flow = Seam::Flow.new
255
+ flow.banana
256
+ flow.mango
257
+
258
+ e = flow.start
259
+ Seam::Effort.find(e.id)
260
+ end
261
+ end
262
+
263
+ let(:effort2_creator) do
264
+ ->() do
265
+ flow = Seam::Flow.new
266
+ flow.apple
267
+ flow.orange
268
+
269
+ e = flow.start
270
+ Seam::Effort.find(e.id)
271
+ end
272
+ end
273
+
274
+ let(:apple_worker) do
275
+ apple_worker = Seam::Worker.new
276
+ apple_worker.handles(:apple)
277
+
278
+ apple_worker.class_eval do
279
+ attr_accessor :count
280
+ end
281
+
282
+ def apple_worker.process
283
+ self.count += 1
284
+ end
285
+
286
+ apple_worker.count = 0
287
+ apple_worker
288
+ end
289
+
290
+ before do
291
+ Timecop.freeze Time.parse('1/6/2013')
292
+
293
+ effort1_creator.call
294
+ effort1_creator.call
295
+ effort1_creator.call
296
+ effort2_creator.call
297
+ effort2_creator.call
298
+
299
+ apple_worker.execute_all
300
+ end
301
+
302
+ it "should call the apple worker for the record in question" do
303
+ apple_worker.count.must_equal 2
304
+ end
305
+ end
306
+
307
+ describe "a more realistic example" do
308
+
309
+ let(:flow) do
310
+ flow = Seam::Flow.new
311
+ flow.wait_for_attempting_contact_stage
312
+ flow.determine_if_postcard_should_be_sent
313
+ flow.send_postcard_if_necessary
314
+ flow
315
+ end
316
+
317
+ let(:effort_creator) do
318
+ ->() do
319
+ e = flow.start
320
+ flow.stamp_data_history = @stamp_data_history
321
+ Seam::Effort.find(e.id)
322
+ end
323
+ end
324
+
325
+ let(:wait_for_attempting_contact_stage_worker) do
326
+ worker = Seam::Worker.new
327
+ worker.handles(:wait_for_attempting_contact_stage)
328
+
329
+ def worker.process
330
+ @current_effort.data['hit 1'] ||= 0
331
+ @current_effort.data['hit 1'] += 1
332
+ move_to_next_step
333
+ end
334
+
335
+ worker
336
+ end
337
+
338
+ let(:determine_if_postcard_should_be_sent_worker) do
339
+ worker = Seam::Worker.new
340
+ worker.handles(:determine_if_postcard_should_be_sent)
341
+
342
+ def worker.process
343
+ @current_effort.data['hit 2'] ||= 0
344
+ @current_effort.data['hit 2'] += 1
345
+ move_to_next_step
346
+ end
347
+
348
+ worker
349
+ end
350
+
351
+ let(:send_postcard_if_necessary_worker) do
352
+ worker = Seam::Worker.new
353
+ worker.handles(:send_postcard_if_necessary)
354
+
355
+ def worker.process
356
+ @current_effort.data['hit 3'] ||= 0
357
+ @current_effort.data['hit 3'] += 1
358
+ move_to_next_step
359
+ end
360
+
361
+ worker
362
+ end
363
+
364
+ before do
365
+ Timecop.freeze Time.parse('1/6/2013')
366
+ end
367
+
368
+ it "should progress through the story" do
369
+
370
+ # SETUP
371
+ effort = effort_creator.call
372
+ effort.next_step.must_equal "wait_for_attempting_contact_stage"
373
+
374
+ # FIRST WAVE
375
+ send_postcard_if_necessary_worker.execute_all
376
+ determine_if_postcard_should_be_sent_worker.execute_all
377
+ wait_for_attempting_contact_stage_worker.execute_all
378
+
379
+ effort = Seam::Effort.find effort.id
380
+ effort.next_step.must_equal "determine_if_postcard_should_be_sent"
381
+
382
+ effort.complete?.must_equal false
383
+
384
+ # SECOND WAVE
385
+ send_postcard_if_necessary_worker.execute_all
386
+ determine_if_postcard_should_be_sent_worker.execute_all
387
+ wait_for_attempting_contact_stage_worker.execute_all
388
+
389
+ effort = Seam::Effort.find effort.id
390
+ effort.next_step.must_equal "send_postcard_if_necessary"
391
+
392
+ # THIRD WAVE
393
+ send_postcard_if_necessary_worker.execute_all
394
+ determine_if_postcard_should_be_sent_worker.execute_all
395
+ wait_for_attempting_contact_stage_worker.execute_all
396
+
397
+ effort = Seam::Effort.find effort.id
398
+ effort.next_step.must_equal nil
399
+
400
+ effort.data['hit 1'].must_equal 1
401
+ effort.data['hit 2'].must_equal 1
402
+ effort.data['hit 3'].must_equal 1
403
+
404
+ effort.complete?.must_equal true
405
+ effort.completed_at.must_equal Time.now
406
+
407
+ # FUTURE WAVES
408
+ send_postcard_if_necessary_worker.execute_all
409
+ determine_if_postcard_should_be_sent_worker.execute_all
410
+ wait_for_attempting_contact_stage_worker.execute_all
411
+ send_postcard_if_necessary_worker.execute_all
412
+ determine_if_postcard_should_be_sent_worker.execute_all
413
+ wait_for_attempting_contact_stage_worker.execute_all
414
+ send_postcard_if_necessary_worker.execute_all
415
+ determine_if_postcard_should_be_sent_worker.execute_all
416
+ wait_for_attempting_contact_stage_worker.execute_all
417
+
418
+ effort = Seam::Effort.find effort.id
419
+ effort.next_step.must_equal nil
420
+
421
+ effort.data['hit 1'].must_equal 1
422
+ effort.data['hit 2'].must_equal 1
423
+ effort.data['hit 3'].must_equal 1
424
+
425
+ end
426
+ end
427
+
428
+ describe "a more realistic example with waiting" do
429
+
430
+ let(:flow) do
431
+ flow = Seam::Flow.new
432
+ flow.wait_for_attempting_contact_stage
433
+ flow.determine_if_postcard_should_be_sent
434
+ flow.send_postcard_if_necessary
435
+ flow
436
+ end
437
+
438
+ let(:effort_creator) do
439
+ ->() do
440
+ e = flow.start
441
+ Seam::Effort.find(e.id)
442
+ end
443
+ end
444
+
445
+ let(:wait_for_attempting_contact_stage_worker) do
446
+ worker = Seam::Worker.new
447
+ worker.handles(:wait_for_attempting_contact_stage)
448
+
449
+ def worker.process
450
+ @current_effort.data['hit 1'] ||= 0
451
+ @current_effort.data['hit 1'] += 1
452
+ if Time.now >= Time.parse('28/12/2013')
453
+ move_to_next_step
454
+ else
455
+ try_again_in 1.day
456
+ end
457
+ end
458
+
459
+ worker
460
+ end
461
+
462
+ let(:determine_if_postcard_should_be_sent_worker) do
463
+ worker = Seam::Worker.new
464
+ worker.handles(:determine_if_postcard_should_be_sent)
465
+
466
+ def worker.process
467
+ @current_effort.data['hit 2'] ||= 0
468
+ @current_effort.data['hit 2'] += 1
469
+ move_to_next_step
470
+ end
471
+
472
+ worker
473
+ end
474
+
475
+ let(:send_postcard_if_necessary_worker) do
476
+ worker = Seam::Worker.new
477
+ worker.handles(:send_postcard_if_necessary)
478
+
479
+ def worker.process
480
+ @current_effort.data['hit 3'] ||= 0
481
+ @current_effort.data['hit 3'] += 1
482
+ move_to_next_step
483
+ end
484
+
485
+ worker
486
+ end
487
+
488
+ before do
489
+ Timecop.freeze Time.parse('25/12/2013')
490
+ end
491
+
492
+ it "should progress through the story" do
493
+
494
+ # SETUP
495
+ effort = effort_creator.call
496
+ effort.next_step.must_equal "wait_for_attempting_contact_stage"
497
+
498
+ # FIRST DAY
499
+ send_postcard_if_necessary_worker.execute_all
500
+ determine_if_postcard_should_be_sent_worker.execute_all
501
+ wait_for_attempting_contact_stage_worker.execute_all
502
+
503
+ effort = Seam::Effort.find effort.id
504
+ effort.next_step.must_equal "wait_for_attempting_contact_stage"
505
+
506
+ send_postcard_if_necessary_worker.execute_all
507
+ determine_if_postcard_should_be_sent_worker.execute_all
508
+ wait_for_attempting_contact_stage_worker.execute_all
509
+ send_postcard_if_necessary_worker.execute_all
510
+ determine_if_postcard_should_be_sent_worker.execute_all
511
+ wait_for_attempting_contact_stage_worker.execute_all
512
+
513
+ effort = Seam::Effort.find effort.id
514
+ effort.next_step.must_equal "wait_for_attempting_contact_stage"
515
+
516
+ Timecop.freeze Time.parse('29/12/2013')
517
+
518
+ send_postcard_if_necessary_worker.execute_all
519
+ determine_if_postcard_should_be_sent_worker.execute_all
520
+ wait_for_attempting_contact_stage_worker.execute_all
521
+
522
+ effort = Seam::Effort.find effort.id
523
+ effort.next_step.must_equal "determine_if_postcard_should_be_sent"
524
+ effort.data['hit 1'].must_equal 2
525
+ end
526
+ end
527
+
528
+ describe "tracking history" do
529
+
530
+ let(:flow) do
531
+ flow = Seam::Flow.new
532
+ flow.wait_for_attempting_contact_stage
533
+ flow.determine_if_postcard_should_be_sent
534
+ flow.send_postcard_if_necessary
535
+ flow
536
+ end
537
+
538
+ let(:effort_creator) do
539
+ ->(values = {}) do
540
+ e = flow.start values
541
+ Seam::Effort.find(e.id)
542
+ end
543
+ end
544
+
545
+ let(:wait_for_attempting_contact_stage_worker) do
546
+ worker = Seam::Worker.new
547
+ worker.handles(:wait_for_attempting_contact_stage)
548
+
549
+ def worker.process
550
+ @current_effort.data['hit 1'] ||= 0
551
+ @current_effort.data['hit 1'] += 1
552
+ if Time.now >= Time.parse('28/12/2013')
553
+ move_to_next_step
554
+ else
555
+ try_again_in 1.day
556
+ end
557
+ end
558
+
559
+ worker
560
+ end
561
+
562
+ let(:determine_if_postcard_should_be_sent_worker) do
563
+ worker = Seam::Worker.new
564
+ worker.handles(:determine_if_postcard_should_be_sent)
565
+
566
+ def worker.process
567
+ @current_effort.data['hit 2'] ||= 0
568
+ @current_effort.data['hit 2'] += 1
569
+ move_to_next_step
570
+ end
571
+
572
+ worker
573
+ end
574
+
575
+ let(:send_postcard_if_necessary_worker) do
576
+ worker = Seam::Worker.new
577
+ worker.handles(:send_postcard_if_necessary)
578
+
579
+ def worker.process
580
+ @current_effort.data['hit 3'] ||= 0
581
+ @current_effort.data['hit 3'] += 1
582
+ move_to_next_step
583
+ end
584
+
585
+ worker
586
+ end
587
+
588
+ before do
589
+ Timecop.freeze Time.parse('26/12/2013')
590
+ end
591
+
592
+ it "should progress through the story" do
593
+
594
+ # SETUP
595
+ effort = effort_creator.call({ first_name: 'DARREN' })
596
+ effort.next_step.must_equal "wait_for_attempting_contact_stage"
597
+
598
+ # FIRST DAY
599
+ send_postcard_if_necessary_worker.execute_all
600
+ determine_if_postcard_should_be_sent_worker.execute_all
601
+ wait_for_attempting_contact_stage_worker.execute_all
602
+
603
+ effort = Seam::Effort.find effort.id
604
+ effort.next_step.must_equal "wait_for_attempting_contact_stage"
605
+
606
+ effort.history.count.must_equal 1
607
+ effort.history[0].contrast_with!( {
608
+ "step_id" => effort.flow['steps'][0]['id'],
609
+ "started_at"=> Time.now,
610
+ "step"=>"wait_for_attempting_contact_stage",
611
+ "stopped_at" => Time.now,
612
+ } )
613
+
614
+ send_postcard_if_necessary_worker.execute_all
615
+ determine_if_postcard_should_be_sent_worker.execute_all
616
+ wait_for_attempting_contact_stage_worker.execute_all
617
+ send_postcard_if_necessary_worker.execute_all
618
+ determine_if_postcard_should_be_sent_worker.execute_all
619
+ wait_for_attempting_contact_stage_worker.execute_all
620
+
621
+ effort = Seam::Effort.find effort.id
622
+ effort.next_step.must_equal "wait_for_attempting_contact_stage"
623
+
624
+ effort.history.count.must_equal 1
625
+ effort.history[0].contrast_with!( {
626
+ "step_id" => effort.flow['steps'][0]['id'],
627
+ "started_at"=> Time.now,
628
+ "step"=>"wait_for_attempting_contact_stage",
629
+ "stopped_at" => Time.now,
630
+ "result" => "try_again_in",
631
+ "try_again_on" => Time.now + 1.day
632
+ } )
633
+
634
+ # THE NEXT DAY
635
+ Timecop.freeze Time.parse('27/12/2013')
636
+
637
+ send_postcard_if_necessary_worker.execute_all
638
+ determine_if_postcard_should_be_sent_worker.execute_all
639
+ wait_for_attempting_contact_stage_worker.execute_all
640
+
641
+ effort = Seam::Effort.find effort.id
642
+ effort.next_step.must_equal "wait_for_attempting_contact_stage"
643
+
644
+ effort.history.count.must_equal 2
645
+ effort.history[1].contrast_with!( {
646
+ "step_id" => effort.flow['steps'][0]['id'],
647
+ "started_at"=> Time.now,
648
+ "step"=>"wait_for_attempting_contact_stage",
649
+ "stopped_at" => Time.now,
650
+ "result" => "try_again_in"
651
+ } )
652
+
653
+ # THE NEXT DAY
654
+ Timecop.freeze Time.parse('28/12/2013')
655
+
656
+ send_postcard_if_necessary_worker.execute_all
657
+ determine_if_postcard_should_be_sent_worker.execute_all
658
+ wait_for_attempting_contact_stage_worker.execute_all
659
+
660
+ effort = Seam::Effort.find effort.id
661
+ effort.next_step.must_equal "determine_if_postcard_should_be_sent"
662
+
663
+ effort.history.count.must_equal 3
664
+ effort.history[2].contrast_with!( {
665
+ "step_id" => effort.flow['steps'][0]['id'],
666
+ "started_at"=> Time.now,
667
+ "step"=>"wait_for_attempting_contact_stage",
668
+ "stopped_at" => Time.now,
669
+ "result" => "move_to_next_step"
670
+ } )
671
+
672
+ # KEEP GOING
673
+ send_postcard_if_necessary_worker.execute_all
674
+ determine_if_postcard_should_be_sent_worker.execute_all
675
+ wait_for_attempting_contact_stage_worker.execute_all
676
+ effort = Seam::Effort.find effort.id
677
+ effort.next_step.must_equal "send_postcard_if_necessary"
678
+
679
+ effort.history.count.must_equal 4
680
+ effort.history[3].contrast_with!( {
681
+ "step_id" => effort.flow['steps'][1]['id'],
682
+ "started_at"=> Time.now,
683
+ "step"=>"determine_if_postcard_should_be_sent",
684
+ "stopped_at" => Time.now,
685
+ "result" => "move_to_next_step"
686
+ } )
687
+
688
+ # KEEP GOING
689
+ send_postcard_if_necessary_worker.execute_all
690
+ determine_if_postcard_should_be_sent_worker.execute_all
691
+ wait_for_attempting_contact_stage_worker.execute_all
692
+ effort = Seam::Effort.find effort.id
693
+ effort.next_step.must_equal nil
694
+
695
+ effort.history.count.must_equal 5
696
+ effort.history[4].contrast_with!( {
697
+ "step_id" => effort.flow['steps'][2]['id'],
698
+ "started_at"=> Time.now,
699
+ "step"=>"send_postcard_if_necessary",
700
+ "stopped_at" => Time.now,
701
+ "result" => "move_to_next_step"
702
+ } )
703
+ end
704
+ end
705
+
706
+ describe "eject" do
707
+
708
+ let(:effort) do
709
+ flow = Seam::Flow.new
710
+ flow.apple
711
+ flow.orange
712
+
713
+ e = flow.start( { first_name: 'John' } )
714
+ Seam::Effort.find(e.id)
715
+ end
716
+
717
+ before do
718
+ Timecop.freeze Time.parse('5/11/2013')
719
+ effort.next_step.must_equal "apple"
720
+
721
+ apple_worker = Seam::Worker.new
722
+ apple_worker.handles(:apple)
723
+ def apple_worker.process
724
+ eject
725
+ end
726
+
727
+ apple_worker.execute effort
728
+ end
729
+
730
+ it "should mark the step as completed" do
731
+ fresh_effort = Seam::Effort.find(effort.id)
732
+ fresh_effort.complete?.must_equal true
733
+ end
734
+
735
+ it "should mark the next step to nil" do
736
+ fresh_effort = Seam::Effort.find(effort.id)
737
+ fresh_effort.next_step.nil?.must_equal true
738
+ end
739
+
740
+ it "should mark the completed_at date" do
741
+ fresh_effort = Seam::Effort.find(effort.id)
742
+ fresh_effort.completed_at.must_equal Time.now
743
+ end
744
+
745
+ it "should mark the history" do
746
+ effort.history[0].contrast_with!({"step"=>"apple", "result" => "eject" } )
747
+ end
748
+
749
+ end
750
+
751
+ describe "use the name of the worker to tie to a step" do
752
+
753
+ let(:effort) do
754
+ flow = Seam::Flow.new
755
+ flow.i_will_not_call_handles
756
+
757
+ e = flow.start
758
+ Seam::Effort.find(e.id)
759
+ end
760
+
761
+ before do
762
+ effort
763
+ worker = IWillNotCallHandlesWorker.new
764
+ IWillNotCallHandlesWorker.new.execute_all
765
+ end
766
+
767
+ it "should complete the effort" do
768
+ fresh_effort = Seam::Effort.find effort.id
769
+ fresh_effort.complete?.must_equal true
770
+ end
771
+
772
+ end
773
+
774
+ describe "making the current step available" do
775
+ it "should return the first step if on the first step" do
776
+ flow = Seam::Flow.new
777
+ flow.apple("test")
778
+ flow.orange
779
+
780
+ effort = flow.start( { first_name: 'John' } )
781
+ effort = Seam::Effort.find(effort.id)
782
+
783
+ effort.next_step.must_equal "apple"
784
+
785
+ apple_worker = Seam::Worker.new
786
+ apple_worker.handles(:apple)
787
+ def apple_worker.process
788
+ current_step.nil?.must_equal false
789
+ current_step["name"].must_equal "apple"
790
+ current_step["arguments"].must_equal ["test"]
791
+ end
792
+
793
+ apple_worker.execute effort
794
+ end
795
+
796
+ it "should return the second step if on the second step" do
797
+ flow = Seam::Flow.new
798
+ flow.apple("test")
799
+ flow.orange("another test")
800
+
801
+ effort = flow.start( { first_name: 'John' } )
802
+ effort = Seam::Effort.find(effort.id)
803
+
804
+ effort.next_step.must_equal "apple"
805
+
806
+ apple_worker = Seam::Worker.new
807
+ apple_worker.handles(:apple)
808
+ def apple_worker.process
809
+ current_step.nil?.must_equal false
810
+ current_step["name"].must_equal "apple"
811
+ current_step["arguments"].must_equal ["test"]
812
+ end
813
+
814
+ orange_worker = Seam::Worker.new
815
+ orange_worker.handles(:orange)
816
+ def orange_worker.process
817
+ current_step.nil?.must_equal false
818
+ current_step["name"].must_equal "orange"
819
+ current_step["arguments"].must_equal ["another test"]
820
+ end
821
+
822
+ apple_worker.execute_all
823
+ orange_worker.execute_all
824
+ end
825
+ end
826
+
827
+ describe "data history" do
828
+ describe "stamping the history" do
829
+ let(:effort) do
830
+ flow = Seam::Flow.new
831
+ flow.stamp_data_history = true
832
+ flow.apple
833
+
834
+ e = flow.start( { first_name: 'John' } )
835
+ Seam::Effort.find(e.id)
836
+ end
837
+
838
+ before do
839
+ Timecop.freeze Time.parse('3/4/2013')
840
+ effort.next_step.must_equal "apple"
841
+
842
+ apple_worker = Seam::Worker.new
843
+ apple_worker.handles(:apple)
844
+ def apple_worker.process
845
+ effort.data['something'] = 'else'
846
+ end
847
+
848
+ apple_worker.execute effort
849
+ end
850
+
851
+ it "should not update the next step" do
852
+ fresh_effort = Seam::Effort.find(effort.id)
853
+ fresh_effort.history.count.must_equal 1
854
+ end
855
+
856
+ it "should set the data_before history" do
857
+ fresh_effort = Seam::Effort.find(effort.id)
858
+ fresh_effort.history.first["data_before"].must_equal( { "first_name" => 'John' } )
859
+ end
860
+
861
+ it "should set the data_after history" do
862
+ fresh_effort = Seam::Effort.find(effort.id)
863
+ fresh_effort.history.first["data_after"].must_equal( { "first_name" => 'John', "something" => 'else' } )
864
+ end
865
+ end
866
+
867
+ describe "not stamping the history" do
868
+ let(:effort) do
869
+ flow = Seam::Flow.new
870
+ flow.stamp_data_history = false
871
+ flow.apple
872
+
873
+ e = flow.start( { first_name: 'John' } )
874
+ Seam::Effort.find(e.id)
875
+ end
876
+
877
+ before do
878
+ Timecop.freeze Time.parse('3/4/2013')
879
+
880
+ apple_worker = Seam::Worker.new
881
+ apple_worker.handles(:apple)
882
+ def apple_worker.process
883
+ effort.data['something'] = 'else'
884
+ end
885
+
886
+ apple_worker.execute effort
887
+ end
888
+
889
+ it "should not update the next step" do
890
+ fresh_effort = Seam::Effort.find(effort.id)
891
+ fresh_effort.history.count.must_equal 1
892
+ end
893
+
894
+ it "should set the data_before history" do
895
+ fresh_effort = Seam::Effort.find(effort.id)
896
+ fresh_effort.history.first["data_before"].nil?.must_equal true
897
+ end
898
+
899
+ it "should set the data_after history" do
900
+ fresh_effort = Seam::Effort.find(effort.id)
901
+ fresh_effort.history.first["data_after"].nil?.must_equal true
902
+ end
903
+ end
904
+ end
905
+ end
906
+
907
+ class IWillNotCallHandlesWorker < Seam::Worker
908
+ # no calling handles here
909
+ def process; end
910
+ end