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.
- data/README.textile +124 -34
- data/Rakefile +36 -30
- data/lib/no_stdout.rb +1 -1
- data/lib/state-fu.rb +9 -8
- data/lib/state_fu/active_support_lite/array/access.rb +12 -5
- data/lib/state_fu/active_support_lite/array/conversions.rb +10 -4
- data/lib/state_fu/active_support_lite/array/extract_options.rb +5 -4
- data/lib/state_fu/active_support_lite/array/grouping.rb +7 -4
- data/lib/state_fu/active_support_lite/array/random_access.rb +4 -3
- data/lib/state_fu/active_support_lite/array/wrapper.rb +4 -3
- data/lib/state_fu/active_support_lite/array.rb +3 -1
- data/lib/state_fu/active_support_lite/blank.rb +18 -9
- data/lib/state_fu/active_support_lite/cattr_reader.rb +4 -1
- data/lib/state_fu/active_support_lite/keys.rb +8 -3
- data/lib/state_fu/active_support_lite/misc.rb +6 -4
- data/lib/state_fu/active_support_lite/module/delegation.rb +130 -0
- data/lib/state_fu/active_support_lite/module.rb +1 -0
- data/lib/state_fu/active_support_lite/object.rb +5 -2
- data/lib/state_fu/active_support_lite/string.rb +6 -1
- data/lib/state_fu/active_support_lite/symbol.rb +2 -1
- data/lib/state_fu/applicable.rb +41 -0
- data/lib/state_fu/{helper.rb → arrays.rb} +45 -121
- data/lib/state_fu/binding.rb +136 -159
- data/lib/state_fu/core_ext.rb +78 -10
- data/lib/state_fu/event.rb +112 -48
- data/lib/state_fu/exceptions.rb +80 -34
- data/lib/state_fu/executioner.rb +149 -0
- data/lib/state_fu/has_options.rb +16 -0
- data/lib/state_fu/hooks.rb +21 -16
- data/lib/state_fu/interface.rb +80 -83
- data/lib/state_fu/lathe.rb +361 -148
- data/lib/state_fu/logger.rb +122 -45
- data/lib/state_fu/machine.rb +60 -32
- data/lib/state_fu/method_factory.rb +180 -72
- data/lib/state_fu/methodical.rb +17 -0
- data/lib/state_fu/persistence/active_record.rb +6 -1
- data/lib/state_fu/persistence/attribute.rb +1 -0
- data/lib/state_fu/persistence/base.rb +8 -6
- data/lib/state_fu/persistence.rb +94 -23
- data/lib/state_fu/sprocket.rb +26 -11
- data/lib/state_fu/state.rb +8 -27
- data/lib/state_fu/transition.rb +207 -98
- data/lib/state_fu/transition_query.rb +214 -0
- data/lib/state_fu.rb +1 -0
- data/lib/tasks/spec_last.rake +46 -0
- data/lib/tasks/state_fu.rake +57 -0
- data/lib/vizier.rb +61 -61
- data/spec/custom_formatter.rb +49 -0
- data/spec/features/binding_and_transition_helper_mixin_spec.rb +2 -2
- data/spec/features/method_missing_only_once_spec.rb +28 -0
- data/spec/features/not_requirements_spec.rb +83 -46
- data/spec/features/plotter_spec.rb +97 -0
- data/spec/features/shared_log_spec.rb +7 -0
- data/spec/features/singleton_machine_spec.rb +39 -0
- data/spec/features/state_and_array_options_accessor_spec.rb +1 -1
- data/spec/features/{transition_boolean_comparison.rb → transition_boolean_comparison_spec.rb} +29 -18
- data/spec/helper.rb +6 -117
- data/spec/integration/active_record_persistence_spec.rb +18 -4
- data/spec/integration/binding_extension_spec.rb +1 -1
- data/spec/integration/class_accessor_spec.rb +49 -59
- data/spec/integration/event_definition_spec.rb +20 -20
- data/spec/integration/example_01_document_spec.rb +13 -8
- data/spec/integration/example_02_string_spec.rb +3 -2
- data/spec/integration/instance_accessor_spec.rb +16 -19
- data/spec/integration/lathe_extension_spec.rb +2 -2
- data/spec/integration/machine_duplication_spec.rb +59 -37
- data/spec/integration/relaxdb_persistence_spec.rb +6 -3
- data/spec/integration/requirement_reflection_spec.rb +66 -57
- data/spec/integration/state_definition_spec.rb +72 -66
- data/spec/integration/transition_spec.rb +169 -173
- data/spec/spec.opts +5 -3
- data/spec/spec_helper.rb +132 -0
- data/spec/state_fu_spec.rb +870 -0
- data/spec/units/binding_spec.rb +33 -22
- data/spec/units/event_spec.rb +3 -22
- data/spec/units/exceptions_spec.rb +7 -0
- data/spec/units/lathe_spec.rb +7 -7
- data/spec/units/machine_spec.rb +67 -75
- data/spec/units/method_factory_spec.rb +55 -48
- data/spec/units/sprocket_spec.rb +5 -7
- data/spec/units/state_spec.rb +33 -24
- metadata +31 -19
- data/lib/state_fu/active_support_lite/inheritable_attributes.rb +0 -1
- data/lib/state_fu/fu_space.rb +0 -51
- data/lib/state_fu/mock_transition.rb +0 -38
- data/spec/BDD/plotter_spec.rb +0 -115
- data/spec/integration/dynamic_requirement_spec.rb +0 -160
- data/spec/integration/ex_machine_for_accounts_spec.rb +0 -79
- data/spec/integration/sanity_spec.rb +0 -31
- 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.
|
|
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
|
|
72
|
-
@t.current_state.should ==
|
|
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 ==
|
|
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
|
|
128
|
-
@t.current_state.should ==
|
|
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
|
|
228
|
-
lambda { @obj.state_fu.cycle!() }.should raise_error( StateFu::
|
|
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.
|
|
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.
|
|
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.
|
|
257
|
-
lambda { @obj.noop.next! }.should raise_error( StateFu::
|
|
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.
|
|
261
|
-
lambda { @obj.toomany.next! }.should raise_error( StateFu::
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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(
|
|
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(
|
|
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
|
|
459
|
+
it "should raise an StateFu::TransitionNotFound" do
|
|
425
460
|
lambda do
|
|
426
461
|
@obj.state_fu.next!
|
|
427
|
-
end.should raise_error( StateFu::
|
|
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
|
|
467
|
+
it "should raise StateFu::TransitionNotFound" do
|
|
433
468
|
lambda do
|
|
434
469
|
@obj.state_fu.cycle!
|
|
435
|
-
end.should raise_error( StateFu::
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
603
|
+
Klass.state_fu_machine do
|
|
565
604
|
event( :go ) do
|
|
566
605
|
execute do |ctx|
|
|
567
|
-
called
|
|
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
|
-
@
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
704
|
+
Klass.state_fu_machine do
|
|
663
705
|
event( :go ) do
|
|
664
|
-
execute do
|
|
665
|
-
|
|
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
|
-
@
|
|
679
|
-
|
|
680
|
-
|
|
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.
|
|
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].
|
|
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
|
-
|
|
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
|
-
|
|
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( @
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
900
|
-
|
|
910
|
+
pending
|
|
911
|
+
testing = nil
|
|
912
|
+
@obj.__define_singleton_method(:run_exec) do
|
|
913
|
+
testing = t.testing?
|
|
901
914
|
end
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
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
|
-
|
|
938
|
-
t.args.should == [:a, :b]
|
|
939
|
-
t.options.should == {
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
991
|
-
|
|
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.
|
|
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.
|
|
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
|