davidlee-state-fu 0.3.1 → 0.10.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 (90) hide show
  1. data/README.textile +124 -34
  2. data/Rakefile +36 -30
  3. data/lib/no_stdout.rb +1 -1
  4. data/lib/state-fu.rb +9 -8
  5. data/lib/state_fu/active_support_lite/array/access.rb +12 -5
  6. data/lib/state_fu/active_support_lite/array/conversions.rb +10 -4
  7. data/lib/state_fu/active_support_lite/array/extract_options.rb +5 -4
  8. data/lib/state_fu/active_support_lite/array/grouping.rb +7 -4
  9. data/lib/state_fu/active_support_lite/array/random_access.rb +4 -3
  10. data/lib/state_fu/active_support_lite/array/wrapper.rb +4 -3
  11. data/lib/state_fu/active_support_lite/array.rb +3 -1
  12. data/lib/state_fu/active_support_lite/blank.rb +18 -9
  13. data/lib/state_fu/active_support_lite/cattr_reader.rb +4 -1
  14. data/lib/state_fu/active_support_lite/keys.rb +8 -3
  15. data/lib/state_fu/active_support_lite/misc.rb +6 -4
  16. data/lib/state_fu/active_support_lite/module/delegation.rb +130 -0
  17. data/lib/state_fu/active_support_lite/module.rb +1 -0
  18. data/lib/state_fu/active_support_lite/object.rb +5 -2
  19. data/lib/state_fu/active_support_lite/string.rb +6 -1
  20. data/lib/state_fu/active_support_lite/symbol.rb +2 -1
  21. data/lib/state_fu/applicable.rb +41 -0
  22. data/lib/state_fu/{helper.rb → arrays.rb} +45 -121
  23. data/lib/state_fu/binding.rb +136 -159
  24. data/lib/state_fu/core_ext.rb +78 -10
  25. data/lib/state_fu/event.rb +112 -48
  26. data/lib/state_fu/exceptions.rb +80 -34
  27. data/lib/state_fu/executioner.rb +149 -0
  28. data/lib/state_fu/has_options.rb +16 -0
  29. data/lib/state_fu/hooks.rb +21 -16
  30. data/lib/state_fu/interface.rb +80 -83
  31. data/lib/state_fu/lathe.rb +361 -148
  32. data/lib/state_fu/logger.rb +122 -45
  33. data/lib/state_fu/machine.rb +60 -32
  34. data/lib/state_fu/method_factory.rb +180 -72
  35. data/lib/state_fu/methodical.rb +17 -0
  36. data/lib/state_fu/persistence/active_record.rb +6 -1
  37. data/lib/state_fu/persistence/attribute.rb +1 -0
  38. data/lib/state_fu/persistence/base.rb +8 -6
  39. data/lib/state_fu/persistence.rb +94 -23
  40. data/lib/state_fu/sprocket.rb +26 -11
  41. data/lib/state_fu/state.rb +8 -27
  42. data/lib/state_fu/transition.rb +207 -98
  43. data/lib/state_fu/transition_query.rb +214 -0
  44. data/lib/state_fu.rb +1 -0
  45. data/lib/tasks/spec_last.rake +46 -0
  46. data/lib/tasks/state_fu.rake +57 -0
  47. data/lib/vizier.rb +61 -61
  48. data/spec/custom_formatter.rb +49 -0
  49. data/spec/features/binding_and_transition_helper_mixin_spec.rb +2 -2
  50. data/spec/features/method_missing_only_once_spec.rb +28 -0
  51. data/spec/features/not_requirements_spec.rb +83 -46
  52. data/spec/features/plotter_spec.rb +97 -0
  53. data/spec/features/shared_log_spec.rb +7 -0
  54. data/spec/features/singleton_machine_spec.rb +39 -0
  55. data/spec/features/state_and_array_options_accessor_spec.rb +1 -1
  56. data/spec/features/{transition_boolean_comparison.rb → transition_boolean_comparison_spec.rb} +29 -18
  57. data/spec/helper.rb +6 -117
  58. data/spec/integration/active_record_persistence_spec.rb +18 -4
  59. data/spec/integration/binding_extension_spec.rb +1 -1
  60. data/spec/integration/class_accessor_spec.rb +49 -59
  61. data/spec/integration/event_definition_spec.rb +20 -20
  62. data/spec/integration/example_01_document_spec.rb +13 -8
  63. data/spec/integration/example_02_string_spec.rb +3 -2
  64. data/spec/integration/instance_accessor_spec.rb +16 -19
  65. data/spec/integration/lathe_extension_spec.rb +2 -2
  66. data/spec/integration/machine_duplication_spec.rb +59 -37
  67. data/spec/integration/relaxdb_persistence_spec.rb +6 -3
  68. data/spec/integration/requirement_reflection_spec.rb +66 -57
  69. data/spec/integration/state_definition_spec.rb +72 -66
  70. data/spec/integration/transition_spec.rb +169 -173
  71. data/spec/spec.opts +5 -3
  72. data/spec/spec_helper.rb +132 -0
  73. data/spec/state_fu_spec.rb +870 -0
  74. data/spec/units/binding_spec.rb +33 -22
  75. data/spec/units/event_spec.rb +3 -22
  76. data/spec/units/exceptions_spec.rb +7 -0
  77. data/spec/units/lathe_spec.rb +7 -7
  78. data/spec/units/machine_spec.rb +67 -75
  79. data/spec/units/method_factory_spec.rb +55 -48
  80. data/spec/units/sprocket_spec.rb +5 -7
  81. data/spec/units/state_spec.rb +33 -24
  82. metadata +31 -19
  83. data/lib/state_fu/active_support_lite/inheritable_attributes.rb +0 -1
  84. data/lib/state_fu/fu_space.rb +0 -51
  85. data/lib/state_fu/mock_transition.rb +0 -38
  86. data/spec/BDD/plotter_spec.rb +0 -115
  87. data/spec/integration/dynamic_requirement_spec.rb +0 -160
  88. data/spec/integration/ex_machine_for_accounts_spec.rb +0 -79
  89. data/spec/integration/sanity_spec.rb +0 -31
  90. data/spec/units/fu_space_spec.rb +0 -95
@@ -9,13 +9,47 @@ describe StateFu::Transition do
9
9
  make_pristine_class("Klass")
10
10
  end
11
11
 
12
+ describe "transition args / options" do
13
+ before do
14
+ make_pristine_class('Alphabet') do
15
+ machine do
16
+ connect_states :a, :b
17
+ end
18
+ end
19
+ @abc = Alphabet.new
20
+ evt = Alphabet.machine.events[:a_to_b]
21
+ tgt = Alphabet.machine.states[:b]
22
+ @t = @abc.stfu.new_transition(evt, tgt,
23
+ :a, :b, 'c' => 'cat')
24
+ end
25
+
26
+ it "should behave like this" do
27
+ @t.args.should == [:a, :b, {'c' => 'cat'}]
28
+ @t.options.should == {:c => 'cat'}
29
+
30
+ @t.apply!({'d' => :e})
31
+ @t.options.should == {:c => 'cat', :d => :e}
32
+
33
+ @t.args.should == [:a, :b, {'c' => 'cat'}]
34
+
35
+ @t.args = [:A, :B]
36
+ @t.args.should == [:A, :B]
37
+ @t.options.should == {:c => 'cat', :d => :e}
38
+
39
+ @t.args = [:X, :Y, {:scale => :metric }]
40
+
41
+ @t.options.should == { :c => 'cat', :d => :e , :scale => :metric }
42
+ @t.args.options.should == @t.options
43
+ end
44
+ end
45
+
12
46
  #
13
47
  #
14
48
  #
15
49
 
16
50
  describe "A simple machine with 2 states and a single event" do
17
51
  before do
18
- @machine = Klass.machine do
52
+ @machine = Klass.state_fu_machine do
19
53
  state :src do
20
54
  event :transfer, :to => :dest
21
55
  end
@@ -61,15 +95,14 @@ describe StateFu::Transition do
61
95
 
62
96
  it "should be live" do
63
97
  @t.should be_live
64
- @t.should be_real
65
98
  end
66
99
 
67
100
  it "should not be accepted" do
68
101
  @t.should_not be_accepted
69
102
  end
70
103
 
71
- it "should have a current_state of :unfired" do
72
- @t.current_state.should == :unfired
104
+ it "should have a current_state of the origin state" do
105
+ @t.current_state.should == @origin
73
106
  end
74
107
 
75
108
  it "should have a current_hook of nil" do
@@ -90,7 +123,7 @@ describe StateFu::Transition do
90
123
 
91
124
  it "should change the field when persistence is via an attribute" do
92
125
  @obj.state_fu.persister.should be_kind_of( StateFu::Persistence::Attribute )
93
- @obj.state_fu.persister.field_name.should == :state_fu_field
126
+ @obj.state_fu.persister.field_name.to_s.should == StateFu::DEFAULT_FIELD.to_s
94
127
  @obj.send( :state_fu_field ).should == "src"
95
128
  @t.fire!
96
129
  @obj.send( :state_fu_field ).should == "dest"
@@ -117,15 +150,14 @@ describe StateFu::Transition do
117
150
 
118
151
  it "should be live" do
119
152
  @t.should be_live
120
- @t.should be_real
121
153
  end
122
154
 
123
155
  it "should be accepted" do
124
156
  @t.should be_accepted
125
157
  end
126
158
 
127
- it "should have a current_state of :accepted" do
128
- @t.current_state.should == :accepted
159
+ it "should have a current_state of the target state" do
160
+ @t.current_state.should == @target
129
161
  end
130
162
 
131
163
  it "should have a current_hook && current_hook_slot of nil" do
@@ -224,15 +256,18 @@ describe StateFu::Transition do
224
256
  end # state_fu.fire!
225
257
 
226
258
  describe "calling cycle!()" do
227
- it "should raise an InvalidTransition error" do
228
- lambda { @obj.state_fu.cycle!() }.should raise_error( StateFu::InvalidTransition )
259
+ it "should raise a TransitionNotFound error" do
260
+ lambda { @obj.state_fu.cycle!() }.should raise_error( StateFu::TransitionNotFound )
229
261
  end
230
262
  end # cycle!
231
263
 
232
264
  describe "calling next!()" do
233
265
  it "should change the state" do
234
266
  @obj.state_fu.state.should == @origin
235
- @obj.state_fu.next!()
267
+ t = @obj.state_fu.transfer
268
+ t.should be_valid
269
+ @obj.state_fu.valid_transitions.length.should == 1
270
+ @obj.state_fu.next!
236
271
  @obj.state_fu.state.should == @target
237
272
  end
238
273
 
@@ -242,23 +277,23 @@ describe StateFu::Transition do
242
277
  end
243
278
 
244
279
  it "should define any methods declared in a block given to .transition" do
245
- trans = @obj.state_fu.next! do
280
+ trans = @obj.state_fu.next_transition do
246
281
  def snoo
247
282
  return [self]
248
283
  end
249
284
  end
250
285
  trans.should be_kind_of( StateFu::Transition )
251
- trans.should respond_to(:snoo)
286
+ # trans.should respond_to(:snoo)
252
287
  trans.snoo.should == [trans]
253
288
  end
254
289
 
255
290
  it "should raise an error when there is no next state" do
256
- Klass.machine(:noop) {}
257
- lambda { @obj.noop.next! }.should raise_error( StateFu::InvalidTransition )
291
+ Klass.state_fu_machine(:noop) {}
292
+ lambda { @obj.noop.next! }.should raise_error( StateFu::TransitionNotFound )
258
293
  end
259
294
  it "should raise an error when there is more than one next state" do
260
- Klass.machine(:toomany) { event( :go, :from => :one, :to => [:a,:b,:c] ) }
261
- lambda { @obj.toomany.next! }.should raise_error( StateFu::InvalidTransition )
295
+ Klass.state_fu_machine(:toomany) { event( :go, :from => :one, :to => [:a,:b,:c] ) }
296
+ lambda { @obj.toomany.next! }.should raise_error( StateFu::TransitionNotFound )
262
297
  end
263
298
  end # next!
264
299
 
@@ -268,25 +303,25 @@ describe StateFu::Transition do
268
303
  end
269
304
 
270
305
  describe "calling transition( :transfer, :a, :b, :c => :d )" do
271
- it "should set args to [:a, :b] and options to :c => :d on the transition" do
306
+ it "should set args and options on the transition" do
272
307
  t = @obj.state_fu.transition( :transfer, *@args )
273
- t.args.should == [ :a, :b ]
308
+ t.args.should == [ :a, :b, {:c => :d} ]
274
309
  t.options.should == { :c => :d }
275
310
  end
276
311
  end
277
312
 
278
313
  describe "calling fire!( :transfer, :a, :b, :c => :d )" do
279
- it "should set args to [:a, :b] and options to :c => :d on the transition" do
314
+ it "should set args and options on the transition" do
280
315
  t = @obj.state_fu.fire!( :transfer, *@args )
281
- t.args.should == [ :a, :b ]
316
+ t.args.should == [ :a, :b, {:c =>:d} ]
282
317
  t.options.should == { :c => :d }
283
318
  end
284
319
  end
285
320
 
286
321
  describe "calling next!( :a, :b, :c => :d )" do
287
- it "should set args to [:a, :b] and options to :c => :d on the transition" do
322
+ it "should set args and options on the transition" do
288
323
  t = @obj.state_fu.next!( *@args )
289
- t.args.should == [ :a, :b ]
324
+ t.args.should == [ :a, :b, {:c => :d}]
290
325
  t.options.should == { :c => :d }
291
326
  end
292
327
  end
@@ -301,7 +336,7 @@ describe StateFu::Transition do
301
336
  describe "A simple machine with 1 state and an event cycling at the same state" do
302
337
 
303
338
  before do
304
- @machine = Klass.machine do
339
+ @machine = Klass.state_fu_machine do
305
340
  state :state_fuega do
306
341
  event :transfer, :to => :state_fuega
307
342
  end
@@ -320,8 +355,8 @@ describe StateFu::Transition do
320
355
  end
321
356
 
322
357
  it "should pass args / options to the transition" do
323
- t = @obj.state_fu.cycle!( :a, :b , { :c => :d } )
324
- t.args.should == [ :a, :b ]
358
+ t = @obj.state_fu.cycle!( nil, :a, :b , { :c => :d } )
359
+ t.args.should == [ :a, :b, { :c => :d } ]
325
360
  t.options.should == { :c => :d }
326
361
  end
327
362
 
@@ -347,7 +382,7 @@ describe StateFu::Transition do
347
382
  describe "A simple machine with 3 states and an event to & from multiple states" do
348
383
 
349
384
  before do
350
- @machine = Klass.machine do
385
+ @machine = Klass.state_fu_machine do
351
386
  states :a, :b
352
387
  states :x, :y
353
388
 
@@ -377,23 +412,23 @@ describe StateFu::Transition do
377
412
 
378
413
  describe "state_fu instance methods" do
379
414
  describe "state_fu.transition" do
380
- it "should raise an ArgumentError unless a valid targets state is supplied or can be inferred" do
415
+ it "should raise StateFu::UnknownTarget unless a valid targets state is supplied or can be inferred" do
381
416
  lambda do
382
417
  @obj.state_fu.transition( :go )
383
- end.should raise_error( ArgumentError )
418
+ end.should raise_error( StateFu::UnknownTarget )
384
419
 
385
420
  lambda do
386
421
  @obj.state_fu.transition( [:go, nil] )
387
- end.should raise_error( ArgumentError )
422
+ end.should raise_error( StateFu::UnknownTarget )
388
423
 
389
424
  lambda do
390
425
  @obj.state_fu.transition( [:go, :awol] )
391
- end.should raise_error( ArgumentError )
426
+ end.should raise_error( StateFu::UnknownTarget )
392
427
 
393
428
  lambda do
394
429
  @obj.state_fu.transition( [:go, :x] )
395
430
  @obj.state_fu.transition( [:go, :y] )
396
- end.should_not raise_error( ArgumentError )
431
+ end.should_not raise_error( StateFu::UnknownTarget )
397
432
  end
398
433
 
399
434
  it "should return a transition with the specified destination" do
@@ -409,30 +444,30 @@ describe StateFu::Transition do
409
444
  end # state_fu.transition
410
445
 
411
446
  describe "state_fu.fire!" do
412
- it "should raise an ArgumentError unless a valid targets state is supplied" do
447
+ it "should raise an StateFu::UnknownTarget unless a valid targets state is supplied" do
413
448
  lambda do
414
449
  @obj.state_fu.fire!( :go )
415
- end.should raise_error( ArgumentError )
450
+ end.should raise_error( StateFu::UnknownTarget )
416
451
 
417
452
  lambda do
418
453
  @obj.state_fu.fire!( [ :go, :awol ] )
419
- end.should raise_error( ArgumentError )
454
+ end.should raise_error( StateFu::UnknownTarget )
420
455
  end
421
456
  end # state_fu.fire!
422
457
 
423
458
  describe "state_fu.next!" do
424
- it "should raise an ArgumentError" do
459
+ it "should raise an StateFu::TransitionNotFound" do
425
460
  lambda do
426
461
  @obj.state_fu.next!
427
- end.should raise_error( StateFu::InvalidTransition )
462
+ end.should raise_error( StateFu::TransitionNotFound )
428
463
  end
429
464
  end # next!
430
465
 
431
466
  describe "state_fu.cycle!" do
432
- it "should raise an ArgumentError" do
467
+ it "should raise StateFu::TransitionNotFound" do
433
468
  lambda do
434
469
  @obj.state_fu.cycle!
435
- end.should raise_error( StateFu::InvalidTransition )
470
+ end.should raise_error( StateFu::TransitionNotFound )
436
471
  end
437
472
  end # cycle!
438
473
 
@@ -441,7 +476,26 @@ describe StateFu::Transition do
441
476
 
442
477
  describe "A simple machine w/ 2 states, 1 event and named hooks " do
443
478
  before do
444
- @machine = Klass.machine do
479
+ Klass.class_eval do
480
+ attr_reader :calls
481
+
482
+ def called name
483
+ (@calls ||= [])<< name
484
+ end
485
+
486
+ def before_go ; called :before_go end
487
+ def after_go ; called :after_go end
488
+ def execute_go ; called :execute_go end
489
+ def entering_a ; called :entering_a end
490
+ def accepted_a ; called :accepted_a end
491
+ def exiting_a ; called :exiting_a end
492
+ def entering_b ; called :entering_b end
493
+ def accepted_b ; called :accepted_b end
494
+ def exiting_b ; called :exiting_b end
495
+
496
+ end
497
+
498
+ @machine = Klass.state_fu_machine do
445
499
 
446
500
  state :a do
447
501
  on_exit( :exiting_a )
@@ -515,32 +569,16 @@ describe StateFu::Transition do
515
569
  describe "fire! calling hooks" do
516
570
  before do
517
571
  @t = @obj.state_fu.transition( :go )
518
- stub( @obj ).before_go(@t) { @called << :before_go }
519
- stub( @obj ).exiting_a(@t) { @called << :exiting_a }
520
- stub( @obj ).execute_go(@t) { @called << :execute_go }
521
- stub( @obj ).entering_b(@t) { @called << :entering_b }
522
- stub( @obj ).after_go(@t) { @called << :after_go }
523
- stub( @obj ).accepted_b(@t) { @called << :accepted_b }
524
- @called = []
525
- [ :before_go,
526
- :exiting_a,
527
- :execute_go,
528
- :entering_b,
529
- :after_go,
530
- :accepted_b ].each do |method_name|
531
- set_method_arity( @obj, method_name, 1 )
532
- end
533
572
  end
534
573
 
535
574
  it "should update the object's state after state:entering and before event:after" do
536
575
  @binding = @obj.state_fu
537
- mock( @obj ).entering_b( @t ) { @binding.state.name.should == :a }
538
- mock( @obj ).after_go(@t) { @binding.state.name.should == :b }
539
- mock( @obj ).accepted_b(@t) { @binding.state.name.should == :b }
576
+ pending
540
577
  @t.fire!
541
578
  end
542
579
 
543
580
  it "should be accepted after state:entering and before event:after" do
581
+ pending
544
582
  mock( @obj ).entering_b( @t ) { @t.should_not be_accepted }
545
583
  mock( @obj ).after_go(@t) { @t.should be_accepted }
546
584
  mock( @obj ).accepted_b(@t) { @t.should be_accepted }
@@ -548,6 +586,7 @@ describe StateFu::Transition do
548
586
  end
549
587
 
550
588
  it "should call the method for each hook on @obj in order, with the transition" do
589
+ pending
551
590
  mock( @obj ).before_go(@t) { @called << :before_go }
552
591
  mock( @obj ).exiting_a(@t) { @called << :exiting_a }
553
592
  mock( @obj ).execute_go(@t) { @called << :execute_go }
@@ -561,10 +600,10 @@ describe StateFu::Transition do
561
600
  describe "adding an anonymous hook for event.hooks[:execute]" do
562
601
  before do
563
602
  called = @called # get us a ref for the closure
564
- Klass.machine do
603
+ Klass.state_fu_machine do
565
604
  event( :go ) do
566
605
  execute do |ctx|
567
- called << :execute_proc
606
+ called( :execute_proc )
568
607
  end
569
608
  end
570
609
  end
@@ -575,18 +614,19 @@ describe StateFu::Transition do
575
614
  @event.hooks[:execute].first.class.should == Symbol
576
615
  @event.hooks[:execute].last.class.should == Proc
577
616
  @t.fire!()
578
- @called.should == [ :before_go,
579
- :exiting_a,
580
- :execute_go,
581
- :execute_proc,
582
- :entering_b,
583
- :after_go,
584
- :accepted_b ]
617
+ @obj.calls.should == [ :before_go,
618
+ :exiting_a,
619
+ :execute_go,
620
+ :execute_proc,
621
+ :entering_b,
622
+ :after_go,
623
+ :accepted_b ]
585
624
  end
586
625
 
587
626
  it "should be replace the previous proc for a slot if redefined" do
627
+ pending
588
628
  called = @called # get us a ref for the closure
589
- Klass.machine do
629
+ Klass.state_fu_machine do
590
630
  event( :go ) do
591
631
  execute do |ctx|
592
632
  called << :execute_proc_2
@@ -612,8 +652,9 @@ describe StateFu::Transition do
612
652
  describe "adding a named hook with a block" do
613
653
  describe "with arity of -1/0" do
614
654
  it "should call the block in the context of the transition" do
655
+ pending
615
656
  called = @called # get us a ref for the closure
616
- Klass.machine do
657
+ Klass.state_fu_machine do
617
658
  event( :go ) do
618
659
  execute(:named_execute) do
619
660
  raise self.class.inspect unless self.is_a?( StateFu::Transition )
@@ -634,8 +675,9 @@ describe StateFu::Transition do
634
675
 
635
676
  describe "with arity of 1" do
636
677
  it "should call the proc in the context of the object, passing the transition as the argument" do
678
+ pending
637
679
  called = @called # get us a ref for the closure
638
- Klass.machine do
680
+ Klass.state_fu_machine do
639
681
  event( :go ) do
640
682
  execute(:named_execute) do |ctx|
641
683
  raise ctx.class.inspect unless ctx.is_a?( StateFu::Transition )
@@ -659,10 +701,10 @@ describe StateFu::Transition do
659
701
  describe "halting the transition during the execute hook" do
660
702
 
661
703
  before do
662
- Klass.machine do
704
+ Klass.state_fu_machine do
663
705
  event( :go ) do
664
- execute do |ctx|
665
- ctx.halt!("stop")
706
+ execute do
707
+ halt!("stop")
666
708
  end
667
709
  end
668
710
  end
@@ -675,9 +717,9 @@ describe StateFu::Transition do
675
717
  @t.should be_kind_of( StateFu::Transition )
676
718
  @t.should be_halted
677
719
  @t.should_not be_accepted
678
- @called.should == [ :before_go,
679
- :exiting_a,
680
- :execute_go ]
720
+ @obj.calls.flatten.should == [ :before_go,
721
+ :exiting_a,
722
+ :execute_go ]
681
723
  end
682
724
 
683
725
  it "should have current_hook_slot set to where it halted" do
@@ -699,25 +741,31 @@ describe StateFu::Transition do
699
741
 
700
742
  describe "A binding for a machine with an event transition requirement" do
701
743
  before do
702
- @machine = Klass.machine do
744
+ @machine = Klass.state_fu_machine do
703
745
  event( :go, :from => :a, :to => :b ) do
704
746
  requires( :ok? )
705
747
  end
706
748
 
707
749
  initial_state :a
708
750
  end
751
+ Klass.class_eval do
752
+ attr_accessor :ok
753
+ def ok?; ok; end
754
+ end
709
755
  @obj = Klass.new
710
756
  @binding = @obj.state_fu
711
757
  @event = @machine.events[:go]
712
758
  @a = @machine.states[:a]
713
759
  @b = @machine.states[:b]
760
+ # stub(@obj).ok? { true }
714
761
  end
715
762
 
716
763
  describe "when no block is supplied for the requirement" do
717
764
 
718
765
  it "should have an event named :go" do
719
766
  @machine.events[:go].requirements.should == [:ok?]
720
- @machine.events[:go].should be_complete
767
+ @machine.events[:go].targets.should_not be_blank
768
+ @machine.events[:go].origins.should_not be_blank
721
769
  @machine.states.map(&:name).sort_by(&:to_s).should == [:a, :b]
722
770
  @a.should be_kind_of( StateFu::State )
723
771
  @event.should be_kind_of( StateFu::Event )
@@ -728,33 +776,26 @@ describe StateFu::Transition do
728
776
  @binding.events.should_not be_empty
729
777
  end
730
778
 
731
- it "should contain :go in @binding.valid_events if evt.fireable_by? is true for the binding" do
732
- mock( @event ).fireable_by?( @binding ) { true }
733
- @binding.valid_events.should == [@event]
734
- end
735
-
736
- it "should contain :go in @binding.valid_events if @binding.evaluate_requirement( :ok? ) is true" do
737
- mock( @binding ).evaluate_requirement_with_args( :ok? ) { true }
738
- @binding.current_state.should == @machine.initial_state
739
- @binding.events.should == @machine.events
740
- @binding.valid_events.should == [@event]
741
- end
742
779
 
743
780
  it "should contain the event in @binding.valid_events if @obj.ok? is true" do
744
- mock( @obj ).ok? { true }
781
+ # stub( @binding ).ok?() { true }
782
+ # set_method_arity(@binding,:ok, 0)
783
+ @obj.ok = true
745
784
  @binding.current_state.should == @machine.initial_state
746
785
  @binding.events.should == @machine.events
747
786
  @binding.valid_events.should == [@event]
748
787
  end
749
788
 
750
789
  it "should not contain :go in @binding.valid_events if !@obj.ok?" do
751
- mock( @obj ).ok? { false }
790
+ # stub( @binding ).ok?() { false }
791
+ @obj.ok = false
752
792
  @binding.events.should == @machine.events
753
793
  @binding.valid_events.should == []
754
794
  end
755
795
 
756
796
  it "should raise a RequirementError if requirements are not satisfied" do
757
- stub( @obj ).ok? { false }
797
+ #stub( @binding ).ok? { false }
798
+ @obj.ok = false
758
799
  lambda do
759
800
  @obj.state_fu.fire!( :go )
760
801
  end.should raise_error( StateFu::RequirementError )
@@ -787,14 +828,22 @@ describe StateFu::Transition do
787
828
 
788
829
  describe "A binding for a machine with a state transition requirement" do
789
830
  before do
790
- @machine = Klass.machine do
831
+ @machine = Klass.state_fu_machine do
791
832
  event( :go, :from => :a, :to => :b )
792
833
  state( :b ) do
793
834
  requires :entry_ok?
794
835
  end
795
836
  end
837
+ Klass.class_eval do
838
+ attr_accessor :entry_ok
839
+ def entry_ok?
840
+ entry_ok
841
+ end
842
+ end
843
+
796
844
  @obj = Klass.new
797
845
  @binding = @obj.state_fu
846
+ @obj.entry_ok = true
798
847
  @event = @machine.events[:go]
799
848
  @a = @machine.states[:a]
800
849
  @b = @machine.states[:b]
@@ -803,30 +852,20 @@ describe StateFu::Transition do
803
852
  describe "when no block is supplied for the requirement" do
804
853
 
805
854
  it "should be valid if @binding.valid_transitions' values includes the state" do
806
- mock( @binding ).valid_transitions{ {@event => [@b] } }
807
- @binding.valid_next_states.should == [@b]
808
- end
809
-
810
- it "should be valid if state is enterable_by?( @binding)" do
811
- mock( @b ).enterable_by?( @binding ) { true }
855
+ t = @binding.transition([@event, @b])
812
856
  @binding.valid_next_states.should == [@b]
813
857
  end
814
858
 
815
- it "should not be valid if state is not enterable_by?( @binding)" do
816
- mock( @b ).enterable_by?( @binding ) { false }
817
- @binding.valid_next_states.should == []
818
- end
819
-
820
859
  it "should be invalid if @obj.entry_ok? is false" do
821
- mock( @obj ).entry_ok? { false }
860
+ #mock( @obj ).entry_ok? { false }
861
+ @obj.entry_ok = false
822
862
  @b.entry_requirements.should == [:entry_ok?]
823
- # @binding.evaluate_requirement( :entry_ok? ).should == false
824
- # @b.enterable_by?( @binding ).should == false
825
863
  @binding.valid_next_states.should == []
826
864
  end
827
865
 
828
866
  it "should be valid if @obj.entry_ok? is true" do
829
- mock( @obj ).entry_ok? { true }
867
+ # mock( @obj ).entry_ok? { true }
868
+ @obj.entry_ok = true
830
869
  @binding.valid_next_states.should == [@b]
831
870
  end
832
871
 
@@ -857,7 +896,7 @@ describe StateFu::Transition do
857
896
  before do
858
897
  reset!
859
898
  make_pristine_class("Klass")
860
- @machine = Klass.machine do
899
+ @machine = Klass.state_fu_machine do
861
900
  event(:run, :from => :start, :to => :finish ) do
862
901
  execute( :run_exec )
863
902
  end
@@ -867,43 +906,16 @@ describe StateFu::Transition do
867
906
 
868
907
  describe "a method defined on the stateful object" do
869
908
 
870
- # it "should have self as the object itself" do
871
- # called = false
872
- # Klass.class_eval do
873
- # @@obj = nil
874
- # cattr_accessor :obj
875
- #
876
- # def run_exec( t )
877
- # called = true
878
- # raise "self is #{self} not #{@@obj}" unless self == @@obj
879
- # end
880
- # end
881
- # Klass.obj = @obj
882
- # called.should == false
883
- # trans = @obj.state_fu.fire!(:run)
884
- # called.should == true
885
- # end
886
-
887
- it "should receive a transition and be able to access the binding, etc through it" do
888
- mock( @obj ).run_exec(is_a(StateFu::Transition)) do |t|
889
- raise "not a transition" unless t.is_a?( StateFu::Transition )
890
- raise "no binding" unless t.binding.is_a?( StateFu::Binding )
891
- raise "no machine" unless t.machine.is_a?( StateFu::Machine )
892
- raise "no object" unless t.object.is_a?( Klass )
893
- end
894
- set_method_arity( @obj, :run_exec, 1 )
895
- trans = @obj.state_fu.fire!(:run)
896
- end
897
-
898
909
  it "should be able to conditionally execute code based on whether the transition is a test" do
899
- mock( @obj ).run_exec(is_a(StateFu::Transition)) do |t|
900
- raise "SHOULD NOT EXECUTE" unless t.testing?
910
+ pending
911
+ testing = nil
912
+ @obj.__define_singleton_method(:run_exec) do
913
+ testing = t.testing?
901
914
  end
902
- set_method_arity( @obj, :run_exec, 1 )
903
- trans = @obj.state_fu.transition( :run )
904
- trans.test_only = true
905
- trans.fire!
906
- trans.should be_accepted
915
+ @obj.state_fu.fire! :run do |t|
916
+ t.test_only = true
917
+ end
918
+ testing.should == true
907
919
  end
908
920
 
909
921
  it "should be able to call methods on the transition mixed in via machine.helper" do
@@ -932,13 +944,13 @@ describe StateFu::Transition do
932
944
  end
933
945
 
934
946
  it "should be able to access the args / options passed to fire! via transition.args" do
947
+ pending
935
948
  # NOTE a trailing hash gets munged into options - not args
936
949
  args = [:a, :b, { 'c' => :d }]
937
- mock( @obj ).run_exec(is_a(StateFu::Transition)) do |t|
938
- t.args.should == [:a, :b]
939
- t.options.should == {:c => :d}
950
+ @obj.__define_singleton_method(:run_exec) do
951
+ t.args.should == [:a, :b,{'c' => :d}]
952
+ t.options.should == {}
940
953
  end
941
- set_method_arity( @obj, :run_exec, 1 )
942
954
  trans = @obj.state_fu.fire!( :run, *args )
943
955
  trans.should be_accepted
944
956
  end
@@ -946,19 +958,16 @@ describe StateFu::Transition do
946
958
 
947
959
  describe "a block passed to binding.transition" do
948
960
  it "should execute in the context of the transition initializer after it's set up" do
949
- Klass.send :define_method, :run_exec, &lambda {|a| raise "!" }
950
-
951
- mock( @obj ).run_exec(is_a(StateFu::Transition)) do |t|
961
+ pending
962
+ @obj.__define_singleton_method(:run_exec) do
952
963
  t.args.should == ['who','yo','daddy?']
953
964
  t.options.should == {:hi => :mum}
954
965
  end
955
- set_method_arity( @obj, :run_exec, 1)
956
966
  trans = @obj.state_fu.transition( :run ) do
957
967
  @args = %w/ who yo daddy? /
958
968
  @options = {:hi => :mum}
969
+
959
970
  end
960
- @obj.method(:run_exec).should be_kind_of(Proc)
961
- @obj.method(:run_exec).arity.should == 1
962
971
  trans.fire!()
963
972
  end
964
973
  end
@@ -968,9 +977,10 @@ describe StateFu::Transition do
968
977
  describe "next_transition" do
969
978
  describe "when there are multiple events but only one is fireable?" do
970
979
  before do
980
+ pending
971
981
  reset!
972
982
  make_pristine_class("Klass")
973
- @machine = Klass.machine do
983
+ @machine = Klass.state_fu_machine do
974
984
  initial_state :alive do
975
985
  event :impossibility do
976
986
  to :afterlife
@@ -987,8 +997,8 @@ describe StateFu::Transition do
987
997
  @obj = Klass.new()
988
998
  @binding = @obj.state_fu
989
999
  @binding.events.length.should == 2
990
- @machine.events[:impossibility].fireable_by?( @binding ).should == false
991
- @machine.events[:inevitability].fireable_by?( @binding ).should == true
1000
+ #@machine.events[:impossibility].fireable_by?( @binding ).should == false
1001
+ #@machine.events[:inevitability].fireable_by?( @binding ).should == true
992
1002
  end
993
1003
 
994
1004
  describe "when the fireable? event has only one target" do
@@ -1006,7 +1016,7 @@ describe StateFu::Transition do
1006
1016
  before do
1007
1017
  reset!
1008
1018
  make_pristine_class("Klass")
1009
- @machine = Klass.machine do
1019
+ @machine = Klass.state_fu_machine do
1010
1020
  initial_state :alive
1011
1021
 
1012
1022
  state :cremated
@@ -1025,13 +1035,9 @@ describe StateFu::Transition do
1025
1035
  @obj = Klass.new()
1026
1036
  @binding = @obj.state_fu
1027
1037
  @machine.events[:inevitability].should be_kind_of(StateFu::Event)
1028
- @machine.events[:inevitability].fireable_by?( @binding ).should == true
1029
- @machine.states[:cremated].enterable_by?( @binding ).should == true
1030
- @machine.states[:buried].enterable_by?( @binding ).should == false
1031
1038
  @binding.valid_events.map(&:name).should == [@machine.events[:inevitability]].map(&:name)
1032
1039
  @binding.valid_events.should == [@machine.events[:inevitability]]
1033
- @binding.valid_transitions.values.flatten.map(&:name).should == [:cremated]
1034
- @binding.valid_transitions.values.flatten.should == [@machine.states[:cremated]]
1040
+ @binding.valid_transitions.map(&:target).map(&:name).should == [:cremated]
1035
1041
  end # before
1036
1042
 
1037
1043
  it "should return a transition for the fireable event & the enterable target" do
@@ -1050,8 +1056,6 @@ describe StateFu::Transition do
1050
1056
  to :cremated, :buried
1051
1057
  end
1052
1058
  end
1053
- @machine.states[:buried].enterable_by?( @binding ).should == true
1054
- @machine.states[:cremated].enterable_by?( @binding ).should == true
1055
1059
  @obj = Klass.new()
1056
1060
  @binding = @obj.state_fu
1057
1061
  end
@@ -1070,11 +1074,3 @@ describe StateFu::Transition do
1070
1074
  end
1071
1075
  end
1072
1076
 
1073
- describe "sanity" do
1074
- include MySpecHelper
1075
- it "should be sane" do
1076
- x = Object.new
1077
- set_method_arity(x, :to_s, 2 )
1078
- x.method( :to_s ).arity.should == 2
1079
- end
1080
- end