state-fu 0.11.1

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 (85) hide show
  1. data/LICENSE +40 -0
  2. data/README.textile +293 -0
  3. data/Rakefile +114 -0
  4. data/lib/binding.rb +292 -0
  5. data/lib/event.rb +192 -0
  6. data/lib/executioner.rb +120 -0
  7. data/lib/hooks.rb +39 -0
  8. data/lib/interface.rb +132 -0
  9. data/lib/lathe.rb +538 -0
  10. data/lib/machine.rb +184 -0
  11. data/lib/method_factory.rb +243 -0
  12. data/lib/persistence.rb +116 -0
  13. data/lib/persistence/active_record.rb +34 -0
  14. data/lib/persistence/attribute.rb +47 -0
  15. data/lib/persistence/base.rb +100 -0
  16. data/lib/persistence/relaxdb.rb +23 -0
  17. data/lib/persistence/session.rb +7 -0
  18. data/lib/sprocket.rb +58 -0
  19. data/lib/state-fu.rb +56 -0
  20. data/lib/state.rb +48 -0
  21. data/lib/support/active_support_lite/array.rb +9 -0
  22. data/lib/support/active_support_lite/array/access.rb +60 -0
  23. data/lib/support/active_support_lite/array/conversions.rb +202 -0
  24. data/lib/support/active_support_lite/array/extract_options.rb +21 -0
  25. data/lib/support/active_support_lite/array/grouping.rb +109 -0
  26. data/lib/support/active_support_lite/array/random_access.rb +13 -0
  27. data/lib/support/active_support_lite/array/wrapper.rb +25 -0
  28. data/lib/support/active_support_lite/blank.rb +67 -0
  29. data/lib/support/active_support_lite/cattr_reader.rb +57 -0
  30. data/lib/support/active_support_lite/keys.rb +57 -0
  31. data/lib/support/active_support_lite/misc.rb +59 -0
  32. data/lib/support/active_support_lite/module.rb +1 -0
  33. data/lib/support/active_support_lite/module/delegation.rb +130 -0
  34. data/lib/support/active_support_lite/object.rb +9 -0
  35. data/lib/support/active_support_lite/string.rb +38 -0
  36. data/lib/support/active_support_lite/symbol.rb +16 -0
  37. data/lib/support/applicable.rb +41 -0
  38. data/lib/support/arrays.rb +197 -0
  39. data/lib/support/core_ext.rb +90 -0
  40. data/lib/support/exceptions.rb +106 -0
  41. data/lib/support/has_options.rb +16 -0
  42. data/lib/support/logger.rb +165 -0
  43. data/lib/support/methodical.rb +17 -0
  44. data/lib/support/no_stdout.rb +55 -0
  45. data/lib/support/plotter.rb +62 -0
  46. data/lib/support/vizier.rb +300 -0
  47. data/lib/tasks/spec_last.rake +55 -0
  48. data/lib/tasks/state_fu.rake +57 -0
  49. data/lib/transition.rb +338 -0
  50. data/lib/transition_query.rb +224 -0
  51. data/spec/custom_formatter.rb +49 -0
  52. data/spec/features/binding_and_transition_helper_mixin_spec.rb +111 -0
  53. data/spec/features/method_missing_only_once_spec.rb +28 -0
  54. data/spec/features/not_requirements_spec.rb +118 -0
  55. data/spec/features/plotter_spec.rb +97 -0
  56. data/spec/features/shared_log_spec.rb +7 -0
  57. data/spec/features/singleton_machine_spec.rb +39 -0
  58. data/spec/features/state_and_array_options_accessor_spec.rb +47 -0
  59. data/spec/features/transition_boolean_comparison_spec.rb +101 -0
  60. data/spec/helper.rb +13 -0
  61. data/spec/integration/active_record_persistence_spec.rb +202 -0
  62. data/spec/integration/binding_extension_spec.rb +41 -0
  63. data/spec/integration/class_accessor_spec.rb +117 -0
  64. data/spec/integration/event_definition_spec.rb +74 -0
  65. data/spec/integration/example_01_document_spec.rb +133 -0
  66. data/spec/integration/example_02_string_spec.rb +88 -0
  67. data/spec/integration/instance_accessor_spec.rb +97 -0
  68. data/spec/integration/lathe_extension_spec.rb +67 -0
  69. data/spec/integration/machine_duplication_spec.rb +101 -0
  70. data/spec/integration/relaxdb_persistence_spec.rb +97 -0
  71. data/spec/integration/requirement_reflection_spec.rb +270 -0
  72. data/spec/integration/state_definition_spec.rb +163 -0
  73. data/spec/integration/transition_spec.rb +1033 -0
  74. data/spec/spec.opts +9 -0
  75. data/spec/spec_helper.rb +132 -0
  76. data/spec/state_fu_spec.rb +948 -0
  77. data/spec/units/binding_spec.rb +192 -0
  78. data/spec/units/event_spec.rb +214 -0
  79. data/spec/units/exceptions_spec.rb +82 -0
  80. data/spec/units/lathe_spec.rb +570 -0
  81. data/spec/units/machine_spec.rb +229 -0
  82. data/spec/units/method_factory_spec.rb +366 -0
  83. data/spec/units/sprocket_spec.rb +69 -0
  84. data/spec/units/state_spec.rb +59 -0
  85. metadata +171 -0
@@ -0,0 +1,229 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ ## See state_and_event_common_spec.rb for behaviour shared between
4
+ ## StateFu::State and StateFu::Event
5
+ ##
6
+
7
+ describe StateFu::Machine do
8
+ include MySpecHelper
9
+
10
+ before do
11
+ end
12
+
13
+ describe "class methods" do
14
+ before do
15
+
16
+ end
17
+
18
+ describe "Machine.for_class" do
19
+ describe "when there's no machine defined for the class" do
20
+ before do
21
+ reset!
22
+ make_pristine_class 'Klass'
23
+ # mock( Klass ).machines() { {} }
24
+ end
25
+
26
+ it "should create a new machine and bind! it" do
27
+ @machine = Object.new
28
+ mock( @machine ).bind!( Klass, :moose, nil )
29
+ mock( StateFu::Machine ).new( {} ) { @machine }
30
+ StateFu::Machine.for_class( Klass, :moose )
31
+ end
32
+
33
+ it "should apply the block (via lathe) if one is given" do
34
+ @m = StateFu::Machine.for_class( Klass, :snoo ) do
35
+ state :porpoise
36
+ end
37
+ # mock( Klass ).machines() { {} }
38
+ # @m.states.map(&:name).should == [:porpoise]
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+
45
+ describe "attributes" do
46
+ end
47
+
48
+ describe "instance methods" do
49
+ before do
50
+ reset!
51
+ make_pristine_class 'Klass'
52
+ @m = StateFu::Machine.new
53
+ end
54
+
55
+ describe "helper" do
56
+ it "should add its arguments to the @@helpers array" do
57
+ module Foo; FOO = :foo; end
58
+ module Bar; BAR = :bar; end
59
+ @m.helper Foo, Bar
60
+ @m.helpers.should == [Foo, Bar]
61
+ end
62
+
63
+ end
64
+
65
+ describe ".initialize" do
66
+ it "should apply options to the machine" do
67
+ @m = StateFu::Machine.new( :colour => "blue")
68
+ @m.options.should == {:colour => "blue" }
69
+ end
70
+ end
71
+
72
+ describe ".apply!" do
73
+
74
+ end
75
+
76
+ describe ".bind!" do
77
+ it "should call StateFu::Machine.bind! with itself and its arguments" do
78
+ field_name = :my_field_name
79
+ mock( StateFu::Machine ).bind!( @m, Klass, :newname, field_name ) {}
80
+ @m.bind!( Klass, :newname, field_name )
81
+ end
82
+
83
+ it "should generate a field name if none is given" do
84
+ klass = Klass
85
+ name = :StinkJuice
86
+ field_name = 'stink_juice_field'
87
+ @m.bind!( Klass, name )
88
+ Klass.state_fu_field_names[name].should == 'stink_juice_field'
89
+ end
90
+ end
91
+
92
+ describe ".initial_state=" do
93
+
94
+ it "should set @initial_state given a String, Symbol or State for an existing state" do
95
+ state = StateFu::State.new( @m, :wizzle )
96
+ @m.states << state
97
+ @m.initial_state = state
98
+ @m.initial_state.should == state
99
+ end
100
+
101
+ it "should create the state if it doesnt exist" do
102
+ @m.initial_state = :snoo
103
+ @m.initial_state.should be_kind_of( StateFu::State )
104
+ @m.initial_state.name.should == :snoo
105
+ @m.states.should include( @m.initial_state )
106
+ end
107
+
108
+ it "should raise an ArgumentError given a number or an Array" do
109
+ lambda do @m.initial_state = 6
110
+ end.should raise_error( ArgumentError )
111
+
112
+ lambda do @m.initial_state = [:ping]
113
+ end.should raise_error( ArgumentError )
114
+ end
115
+
116
+ end
117
+
118
+ describe ".initial_state" do
119
+ it "should return nil if there are no states and initial_state= has not been called" do
120
+ @m.states.should == []
121
+ @m.initial_state.should == nil
122
+ end
123
+
124
+ it "should return the first state if one exists" do
125
+ stub( @m ).states() { [:a, :b, :c] }
126
+ @m.initial_state.should == :a
127
+ end
128
+
129
+ end
130
+
131
+ describe ".states" do
132
+ it "should return an array extended with StateFu::StateArray" do
133
+ @m.states.should be_kind_of( Array )
134
+ @m.states.extended_by.should include( StateFu::StateArray )
135
+ end
136
+ end
137
+
138
+ describe ".state_names" do
139
+ it "should return a list of symbols of state names" do
140
+ @m.states << StateFu::State.new( @m, :a )
141
+ @m.states << StateFu::State.new( @m, :b )
142
+ @m.state_names.should == [:a, :b ]
143
+ end
144
+ end
145
+
146
+ describe ".events" do
147
+ it "should return an array extended with StateFu::EventArray" do
148
+ @m.events.should be_kind_of( Array )
149
+ @m.events.extended_by.should include( StateFu::EventArray )
150
+ end
151
+ end
152
+
153
+ describe ".event_names" do
154
+ it "should return a list of symbols of event names" do
155
+ @m.events << StateFu::Event.new( @m, :a )
156
+ @m.events << StateFu::Event.new( @m, :b )
157
+ @m.event_names.should == [:a, :b ]
158
+ end
159
+ end
160
+
161
+ describe ".find_or_create_states_by_name" do
162
+ describe "given an array of symbols" do
163
+ it "should return the states named by the symbols if they exist" do
164
+ a = StateFu::State.new( @m, :a )
165
+ b = StateFu::State.new( @m, :b )
166
+ @m.states << a
167
+ @m.states << b
168
+ @m.find_or_create_states_by_name( :a, :b ).should == [a, b]
169
+ @m.find_or_create_states_by_name( [:a, :b] ).should == [a, b]
170
+ end
171
+
172
+ it "should return the states named by the symbols and create them if they don't exist" do
173
+ @m.states.should == []
174
+ res = @m.find_or_create_states_by_name( :a, :b )
175
+ res.should be_kind_of( Array )
176
+ res.length.should == 2
177
+ res.all? { |e| e.class == StateFu::State }.should be_true
178
+ res.map(&:name).should == [ :a, :b ]
179
+ @m.find_or_create_states_by_name( :a, :b ).should == res
180
+ end
181
+ end # arr symbols
182
+
183
+ describe "given an array of states" do
184
+ it "should return the states if they're in the machine's states array" do
185
+ a = StateFu::State.new( @m, :a )
186
+ b = StateFu::State.new( @m, :b )
187
+ @m.states << a
188
+ @m.states << b
189
+ @m.find_or_create_states_by_name( a, b ).should == [a, b]
190
+ @m.find_or_create_states_by_name( [a, b] ).should == [a, b]
191
+ @m.find_or_create_states_by_name( [[a, b]] ).should == [a, b]
192
+ end
193
+
194
+ it "should add the states to the machine's states array if they're absent" do
195
+ a = StateFu::State.new( @m, :a )
196
+ b = StateFu::State.new( @m, :b )
197
+ @m.find_or_create_states_by_name( a, b ).should == [a, b]
198
+ @m.find_or_create_states_by_name( [a, b] ).should == [a, b]
199
+ @m.find_or_create_states_by_name( [[a, b]] ).should == [a, b]
200
+ end
201
+ end # arr states
202
+ end # find_or_create_states_by_name
203
+
204
+ describe "requirement_messages" do
205
+ it "should be a hash" do
206
+ @m.should respond_to(:requirement_messages)
207
+ @m.requirement_messages.should be_kind_of( Hash )
208
+ end
209
+
210
+ it "should be empty by default" do
211
+ @m.requirement_messages.should be_empty
212
+ end
213
+
214
+ end # requirement_messages
215
+
216
+ describe "named_procs" do
217
+ it "should be a hash" do
218
+ @m.should respond_to(:named_procs)
219
+ @m.named_procs.should be_kind_of( Hash )
220
+ end
221
+
222
+ it "should be empty by default" do
223
+ @m.named_procs.should be_empty
224
+ end
225
+
226
+ end # named_procs
227
+
228
+ end # instance methods
229
+ end
@@ -0,0 +1,366 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../helper")
2
+
3
+ describe StateFu::MethodFactory do
4
+ include MySpecHelper
5
+
6
+ # TODO - move to eg method_factory integration spec
7
+ describe "event_methods" do
8
+
9
+ before do
10
+ make_pristine_class('Klass')
11
+ end
12
+
13
+ describe "defined on the stateful instance / object before state_fu has been called" do
14
+
15
+ before do
16
+ @machine = Klass.state_fu_machine do
17
+ event( :simple_event,
18
+ :from => { [:a, :b] => :targ } )
19
+ state( :a ) { cycle }
20
+ end # machine
21
+ @obj = Klass.new
22
+ end
23
+
24
+ describe "when there is a method_missing already defined for the class" do
25
+ before do
26
+ reset!
27
+ make_pristine_class('Klass')
28
+ Klass.class_eval do
29
+ def method_missing method_name, *args
30
+ callme
31
+ end
32
+ end
33
+ Klass.state_fu_machine(){}
34
+ end
35
+ it "should call the original method_missing on an unexpected method call" do
36
+ @k = Klass.new
37
+ mock(@k).callme
38
+ @k.whut?
39
+ end
40
+ end
41
+
42
+ describe "event creation methods" do
43
+ it "should call method_missing" do
44
+ mock( @obj ).method_missing( :simple_event! )
45
+ @obj.simple_event!
46
+ end
47
+
48
+ it "should call state_fu!" do
49
+ mock.proxy( StateFu::Binding ).new( Klass.state_fu_machine, @obj, StateFu::DEFAULT )
50
+ @obj
51
+ @obj.private_methods.map(&:to_sym).should include(:state_fu_field)
52
+ #@obj.should respond_to StateFu::DEFAULT_FIELD
53
+ @obj.state_fu.machine.events.should_not be_empty
54
+ @obj.simple_event!
55
+
56
+ # @obj.should_have_received( :state_fu! )
57
+ end
58
+
59
+ it "should not raise a NoMethodError" do
60
+ lambda { @obj.simple_event! }.should_not raise_error( NoMethodError )
61
+ end
62
+
63
+ it "should call binding.fire!( :simple_event ... ) with any specified args" do
64
+ mock.instance_of( StateFu::Binding ).fire_transition!( is_a(StateFu::Event), is_a(StateFu::State), :aa, :bb, {:cc => "dd"} )
65
+ t = @obj.simple_event!( :aa, :bb, :cc => "dd" )
66
+ end
67
+
68
+ it "should fire the transition" do
69
+ @obj.send(:state_fu_field).should == nil
70
+ t = @obj.simple_event!
71
+ t.should be_accepted
72
+ @obj.send(:state_fu_field).should == 'targ'
73
+ end
74
+ end
75
+ end
76
+
77
+
78
+ describe "defined on the binding" do
79
+ describe "when the event is simple (has only one possible target)" do
80
+ before do
81
+ @machine = Klass.state_fu_machine do
82
+ event( :simple_event,
83
+ :from => { [:a, :b] => :targ } )
84
+ end # machine
85
+ @obj = Klass.new
86
+ @binding = @obj.state_fu
87
+ end # before
88
+
89
+ it "should be simple?" do
90
+ e = @machine.events[:simple_event]
91
+ e.origins.length.should == 2
92
+ e.targets.length.should == 1
93
+ e.should be_simple
94
+ end
95
+
96
+ describe "method which returns an unfired transition" do
97
+ it "should have the same name as the event" do
98
+ @binding.should respond_to(:simple_event)
99
+ end
100
+
101
+ it "should return a new transition if called without any arguments" do
102
+ t = @binding.simple_event()
103
+ t.should be_kind_of( StateFu::Transition )
104
+ t.target.should == @machine.states[:targ]
105
+ t.event.should == @machine.events[:simple_event]
106
+ t.should_not be_fired
107
+ end
108
+
109
+ it "should add any arguments / options it is called with to the transition" do
110
+ t = @binding.simple_event :a, :b, :c, {'d' => 'e'}
111
+ #t.should be_kind_of( StateFu::Transition )
112
+ #t.target.should == @machine.states[:targ]
113
+ #t.event.should == @machine.events[:simple_event]
114
+ t.args.should == [:a,:b,:c,{'d' => 'e'}]
115
+ t.options.should == {:d => 'e'}
116
+ end
117
+ end # transition builder
118
+
119
+ describe "method which tests if the event is can_transition?" do
120
+ it "should have the name of the event suffixed with ?" do
121
+ @binding.should respond_to(:can_simple_event?)
122
+ end
123
+
124
+ it "should be true when the binding says it\'s can_transition?" do
125
+ @binding.can_transition?( :simple_event ).should == true
126
+ @binding.can_simple_event?.should == true
127
+ end
128
+
129
+ it "should be false when the binding says it\'s not can_transition?" do
130
+ mock( @binding ).can_transition?( is_a(StateFu::Event), is_a(StateFu::State) ) { false }
131
+ @binding.can_simple_event?.should == false
132
+ end
133
+ end # can_transition?
134
+
135
+ describe "bang (!) method which creates, fires and returns a transition" do
136
+ it "should have the name of the event suffixed with a bang (!)" do
137
+ @binding.should respond_to(:simple_event!)
138
+ end
139
+
140
+ it "should return a fired transition" do
141
+ t = @binding.simple_event!
142
+ t.should be_kind_of( StateFu::Transition )
143
+ t.should be_fired
144
+ end
145
+
146
+ it "should pass any arguments to the transition as args / options" do
147
+ t = @binding.simple_event!( :a, :b, {'c' => :d } )
148
+ t.should be_kind_of( StateFu::Transition )
149
+ t.args.should == [:a, :b, {'c' => :d} ]
150
+ t.options.should == { :c => :d }
151
+ end
152
+ end # bang!
153
+ end # simple
154
+
155
+ describe "when the event is complex (has more than one possible target)" do
156
+ before do
157
+ @machine = Klass.state_fu_machine do
158
+ state :orphan
159
+ event( :complex_event,
160
+ :from => :home,
161
+ :to => [ :x, :y, :z ] )
162
+ initial_state :home
163
+ end # machine
164
+ @obj = Klass.new
165
+ @binding = @obj.state_fu
166
+ end # before
167
+
168
+ it "should not be simple?" do
169
+ e = @machine.events[:complex_event]
170
+ e.origins.length.should == 1
171
+ e.targets.length.should == 3
172
+ e.should_not be_simple
173
+ end
174
+
175
+ describe "method which returns an unfired transition" do
176
+ it "should have the same name as the event" do
177
+ @binding.should respond_to(:complex_event)
178
+ end
179
+
180
+ it "should raise an error if called without any arguments" do
181
+ lambda { @binding.complex_event() }.should raise_error( ArgumentError )
182
+ end
183
+
184
+ it "should raise an ArgumentError if called with a nonexistent target state" do
185
+ lambda { @binding.complex_event(:nonexistent) }.should raise_error( StateFu::UnknownTarget )
186
+ end
187
+
188
+ it "should raise an IllegalTransition if called with an invalid target state" do
189
+ lambda { @binding.complex_event(:orphan) }.should raise_error( StateFu::IllegalTransition )
190
+ end
191
+
192
+ it "should return a transition to the specified state if supplied a valid state" do
193
+ t = @binding.complex_event( :x )
194
+ t.should be_kind_of( StateFu::Transition )
195
+ t.target.name.should == :x
196
+ end
197
+
198
+ it "should add any arguments / options it is called with to the transition" do
199
+ t = @binding.complex_event(:x,
200
+ :a, :b, :c, {'d' => 'e'})
201
+ t.should be_kind_of( StateFu::Transition )
202
+ t.args.should == [:a,:b,:c,{'d' =>'e'}]
203
+ t.options.should == {:d => 'e'}
204
+ end
205
+ end # transition builder
206
+
207
+ describe "method which tests if the event is can_transition?" do
208
+ it "should have the name of the event suffixed with ?" do
209
+ @binding.should respond_to(:can_complex_event?)
210
+ end
211
+
212
+ it "should require a valid state name" do
213
+ lambda { @binding.can_complex_event?(:nonexistent) }.should raise_error( StateFu::UnknownTarget )
214
+ lambda { @binding.can_complex_event?(:orphan) }.should_not raise_error()
215
+ @binding.can_complex_event?(:orphan).should == false
216
+ lambda { @binding.can_complex_event?(:x) }.should_not raise_error
217
+ end
218
+
219
+ it "should be true when the binding says the event is can_transition? " do
220
+ @binding.can_transition?( :complex_event, :x ).should == true
221
+ @binding.can_complex_event?(:x).should == true
222
+ end
223
+ end # can_transition?
224
+
225
+ describe "bang (!) method which creates, fires and returns a transition" do
226
+ it "should have the name of the event suffixed with a bang (!)" do
227
+ @binding.should respond_to(:complex_event!)
228
+ end
229
+
230
+ it "should require a valid state name" do
231
+ lambda { @binding.complex_event!(:nonexistent) }.should raise_error( StateFu::UnknownTarget )
232
+ lambda { @binding.complex_event!(:orphan) }.should raise_error( StateFu::IllegalTransition )
233
+ lambda { @binding.complex_event!(:x) }.should_not raise_error
234
+ end
235
+
236
+ it "should return a fired transition given a valid state name" do
237
+ t = @binding.complex_event!( :x )
238
+ t.should be_kind_of( StateFu::Transition )
239
+ t.target.should == @machine.states[:x]
240
+ t.should be_fired
241
+ end
242
+
243
+ it "should pass any arguments to the transition as args / options" do
244
+ t = @binding.complex_event!( :x,
245
+ :a, :b, {'c' => :d } )
246
+ t.should be_kind_of( StateFu::Transition )
247
+ t.target.should == @machine.states[:x]
248
+ t.args.should == [:a, :b,{'c' =>:d} ]
249
+ t.options.should == { :c => :d }
250
+ end
251
+ end # bang!
252
+ end # complex_event
253
+
254
+ # TODO move these to binding spec
255
+ describe "cycle and next_state methods" do
256
+ describe "when there is a valid transition available for cycle and next_state" do
257
+ before do
258
+ @machine = Klass.state_fu_machine do
259
+ initial_state :groundhog_day
260
+
261
+ state(:groundhog_day) do
262
+ cycle
263
+ end
264
+
265
+ event(:end_movie, :from => :groundhog_day, :to => :happy_ending)
266
+ end # machine
267
+ @obj = Klass.new
268
+ @binding = @obj.state_fu
269
+ end # before
270
+
271
+ describe "cycle methods:" do
272
+ describe "cycle" do
273
+ it "should return a transition for the cyclical event" do
274
+ t = @binding.cycle
275
+ t.should be_kind_of( StateFu::Transition )
276
+ t.origin.name.should == :groundhog_day
277
+ t.target.name.should == :groundhog_day
278
+ t.should_not be_fired
279
+ end
280
+ end
281
+
282
+ describe "cycle?" do
283
+ end
284
+
285
+ describe "cycle!" do
286
+ end
287
+ end # cycle
288
+
289
+ describe "next_state methods:" do
290
+ describe "next_state" do
291
+ end
292
+
293
+ describe "next_state?" do
294
+ end
295
+
296
+ describe "next_state!" do
297
+ end
298
+ end # next_state
299
+ end # with valid transitions
300
+
301
+ describe "when the machine is empty" do
302
+ before do
303
+ @machine = Klass.state_fu_machine() {}
304
+ @obj = Klass.new
305
+ @binding = @obj.state_fu
306
+ end
307
+
308
+ describe "current_state" do
309
+ it "should be nil" do
310
+ @binding.current_state.should == nil
311
+ end
312
+ end
313
+ describe "cycle methods:" do
314
+ describe "cycle" do
315
+ it "should return nil" do
316
+ @binding.cycle.should == nil
317
+ end
318
+ end
319
+
320
+ describe "cycle?" do
321
+ it "should return nil" do
322
+ @binding.cycle?.should == nil
323
+ end
324
+ end
325
+
326
+ describe "cycle!" do
327
+ it "should raise_error( TransitionNotFound )" do
328
+ lambda { @binding.cycle!.should == nil }.should raise_error( StateFu::TransitionNotFound )
329
+ end
330
+ end
331
+ end # cycle
332
+
333
+ describe "next_state methods:" do
334
+ describe "next_state" do
335
+ it "should return nil" do
336
+ @binding.next_state.should == nil
337
+ end
338
+ end
339
+
340
+ describe "next_state?" do
341
+ it "should return nil" do
342
+ pending
343
+ @binding.next_state?.should == nil
344
+ end
345
+ end
346
+
347
+ describe "next_state!" do
348
+ it "should raise_error( IllegalTransition )" do
349
+ lambda { @binding.next_state! }.should raise_error( StateFu::TransitionNotFound )
350
+ end
351
+ end
352
+ end # next_state
353
+
354
+ end # empty machine
355
+
356
+ describe "when there is more than one candidate event / state" do
357
+ end # too many candidates
358
+
359
+ end # cycle & next_state
360
+ end # defined on binding
361
+
362
+ describe "methods defined on the object" do
363
+ end
364
+
365
+ end # event methods
366
+ end