state-fu 0.11.1

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