seam-active_record 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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