hsume2-state_machine 1.0.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 (110) hide show
  1. data/CHANGELOG.rdoc +413 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +717 -0
  4. data/Rakefile +77 -0
  5. data/examples/AutoShop_state.png +0 -0
  6. data/examples/Car_state.png +0 -0
  7. data/examples/TrafficLight_state.png +0 -0
  8. data/examples/Vehicle_state.png +0 -0
  9. data/examples/auto_shop.rb +11 -0
  10. data/examples/car.rb +19 -0
  11. data/examples/merb-rest/controller.rb +51 -0
  12. data/examples/merb-rest/model.rb +28 -0
  13. data/examples/merb-rest/view_edit.html.erb +24 -0
  14. data/examples/merb-rest/view_index.html.erb +23 -0
  15. data/examples/merb-rest/view_new.html.erb +13 -0
  16. data/examples/merb-rest/view_show.html.erb +17 -0
  17. data/examples/rails-rest/controller.rb +43 -0
  18. data/examples/rails-rest/migration.rb +11 -0
  19. data/examples/rails-rest/model.rb +23 -0
  20. data/examples/rails-rest/view_edit.html.erb +25 -0
  21. data/examples/rails-rest/view_index.html.erb +23 -0
  22. data/examples/rails-rest/view_new.html.erb +14 -0
  23. data/examples/rails-rest/view_show.html.erb +17 -0
  24. data/examples/traffic_light.rb +7 -0
  25. data/examples/vehicle.rb +31 -0
  26. data/init.rb +1 -0
  27. data/lib/state_machine.rb +448 -0
  28. data/lib/state_machine/alternate_machine.rb +79 -0
  29. data/lib/state_machine/assertions.rb +36 -0
  30. data/lib/state_machine/branch.rb +224 -0
  31. data/lib/state_machine/callback.rb +236 -0
  32. data/lib/state_machine/condition_proxy.rb +94 -0
  33. data/lib/state_machine/error.rb +13 -0
  34. data/lib/state_machine/eval_helpers.rb +86 -0
  35. data/lib/state_machine/event.rb +304 -0
  36. data/lib/state_machine/event_collection.rb +139 -0
  37. data/lib/state_machine/extensions.rb +149 -0
  38. data/lib/state_machine/initializers.rb +4 -0
  39. data/lib/state_machine/initializers/merb.rb +1 -0
  40. data/lib/state_machine/initializers/rails.rb +25 -0
  41. data/lib/state_machine/integrations.rb +110 -0
  42. data/lib/state_machine/integrations/active_model.rb +502 -0
  43. data/lib/state_machine/integrations/active_model/locale.rb +11 -0
  44. data/lib/state_machine/integrations/active_model/observer.rb +45 -0
  45. data/lib/state_machine/integrations/active_model/versions.rb +31 -0
  46. data/lib/state_machine/integrations/active_record.rb +424 -0
  47. data/lib/state_machine/integrations/active_record/locale.rb +20 -0
  48. data/lib/state_machine/integrations/active_record/versions.rb +143 -0
  49. data/lib/state_machine/integrations/base.rb +91 -0
  50. data/lib/state_machine/integrations/data_mapper.rb +392 -0
  51. data/lib/state_machine/integrations/data_mapper/observer.rb +210 -0
  52. data/lib/state_machine/integrations/data_mapper/versions.rb +62 -0
  53. data/lib/state_machine/integrations/mongo_mapper.rb +272 -0
  54. data/lib/state_machine/integrations/mongo_mapper/locale.rb +4 -0
  55. data/lib/state_machine/integrations/mongo_mapper/versions.rb +110 -0
  56. data/lib/state_machine/integrations/mongoid.rb +357 -0
  57. data/lib/state_machine/integrations/mongoid/locale.rb +4 -0
  58. data/lib/state_machine/integrations/mongoid/versions.rb +18 -0
  59. data/lib/state_machine/integrations/sequel.rb +428 -0
  60. data/lib/state_machine/integrations/sequel/versions.rb +36 -0
  61. data/lib/state_machine/machine.rb +1873 -0
  62. data/lib/state_machine/machine_collection.rb +87 -0
  63. data/lib/state_machine/matcher.rb +123 -0
  64. data/lib/state_machine/matcher_helpers.rb +54 -0
  65. data/lib/state_machine/node_collection.rb +157 -0
  66. data/lib/state_machine/path.rb +120 -0
  67. data/lib/state_machine/path_collection.rb +90 -0
  68. data/lib/state_machine/state.rb +271 -0
  69. data/lib/state_machine/state_collection.rb +112 -0
  70. data/lib/state_machine/transition.rb +458 -0
  71. data/lib/state_machine/transition_collection.rb +244 -0
  72. data/lib/tasks/state_machine.rake +1 -0
  73. data/lib/tasks/state_machine.rb +27 -0
  74. data/test/files/en.yml +17 -0
  75. data/test/files/switch.rb +11 -0
  76. data/test/functional/alternate_state_machine_test.rb +122 -0
  77. data/test/functional/state_machine_test.rb +993 -0
  78. data/test/test_helper.rb +4 -0
  79. data/test/unit/assertions_test.rb +40 -0
  80. data/test/unit/branch_test.rb +890 -0
  81. data/test/unit/callback_test.rb +701 -0
  82. data/test/unit/condition_proxy_test.rb +328 -0
  83. data/test/unit/error_test.rb +43 -0
  84. data/test/unit/eval_helpers_test.rb +222 -0
  85. data/test/unit/event_collection_test.rb +358 -0
  86. data/test/unit/event_test.rb +985 -0
  87. data/test/unit/integrations/active_model_test.rb +1097 -0
  88. data/test/unit/integrations/active_record_test.rb +2021 -0
  89. data/test/unit/integrations/base_test.rb +99 -0
  90. data/test/unit/integrations/data_mapper_test.rb +1909 -0
  91. data/test/unit/integrations/mongo_mapper_test.rb +1611 -0
  92. data/test/unit/integrations/mongoid_test.rb +1591 -0
  93. data/test/unit/integrations/sequel_test.rb +1523 -0
  94. data/test/unit/integrations_test.rb +61 -0
  95. data/test/unit/invalid_event_test.rb +20 -0
  96. data/test/unit/invalid_parallel_transition_test.rb +18 -0
  97. data/test/unit/invalid_transition_test.rb +77 -0
  98. data/test/unit/machine_collection_test.rb +599 -0
  99. data/test/unit/machine_test.rb +3043 -0
  100. data/test/unit/matcher_helpers_test.rb +37 -0
  101. data/test/unit/matcher_test.rb +155 -0
  102. data/test/unit/node_collection_test.rb +217 -0
  103. data/test/unit/path_collection_test.rb +266 -0
  104. data/test/unit/path_test.rb +485 -0
  105. data/test/unit/state_collection_test.rb +310 -0
  106. data/test/unit/state_machine_test.rb +31 -0
  107. data/test/unit/state_test.rb +924 -0
  108. data/test/unit/transition_collection_test.rb +2102 -0
  109. data/test/unit/transition_test.rb +1541 -0
  110. metadata +207 -0
@@ -0,0 +1,310 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class StateCollectionByDefaultTest < Test::Unit::TestCase
4
+ def setup
5
+ @machine = StateMachine::Machine.new(Class.new)
6
+ @states = StateMachine::StateCollection.new(@machine)
7
+ end
8
+
9
+ def test_should_not_have_any_nodes
10
+ assert_equal 0, @states.length
11
+ end
12
+
13
+ def test_should_have_a_machine
14
+ assert_equal @machine, @states.machine
15
+ end
16
+
17
+ def test_should_be_empty_by_priority
18
+ assert_equal [], @states.by_priority
19
+ end
20
+ end
21
+
22
+ class StateCollectionTest < Test::Unit::TestCase
23
+ def setup
24
+ @klass = Class.new
25
+ @machine = StateMachine::Machine.new(@klass)
26
+ @states = StateMachine::StateCollection.new(@machine)
27
+
28
+ @states << @nil = StateMachine::State.new(@machine, nil)
29
+ @states << @parked = StateMachine::State.new(@machine, :parked)
30
+ @states << @idling = StateMachine::State.new(@machine, :idling)
31
+ @machine.states.concat(@states)
32
+
33
+ @object = @klass.new
34
+ end
35
+
36
+ def test_should_index_by_name
37
+ assert_equal @parked, @states[:parked, :name]
38
+ end
39
+
40
+ def test_should_index_by_name_by_default
41
+ assert_equal @parked, @states[:parked]
42
+ end
43
+
44
+ def test_should_index_by_qualified_name
45
+ assert_equal @parked, @states[:parked, :qualified_name]
46
+ end
47
+
48
+ def test_should_index_by_value
49
+ assert_equal @parked, @states['parked', :value]
50
+ end
51
+
52
+ def test_should_not_match_if_value_does_not_match
53
+ assert !@states.matches?(@object, :parked)
54
+ assert !@states.matches?(@object, :idling)
55
+ end
56
+
57
+ def test_should_match_if_value_matches
58
+ assert @states.matches?(@object, nil)
59
+ end
60
+
61
+ def test_raise_exception_if_matching_invalid_state
62
+ assert_raise(IndexError) { @states.matches?(@object, :invalid) }
63
+ end
64
+
65
+ def test_should_find_state_for_object_if_value_is_known
66
+ @object.state = 'parked'
67
+ assert_equal @parked, @states.match(@object)
68
+ end
69
+
70
+ def test_should_find_bang_state_for_object_if_value_is_known
71
+ @object.state = 'parked'
72
+ assert_equal @parked, @states.match!(@object)
73
+ end
74
+
75
+ def test_should_not_find_state_for_object_with_unknown_value
76
+ @object.state = 'invalid'
77
+ assert_nil @states.match(@object)
78
+ end
79
+
80
+ def test_should_raise_exception_if_finding_bang_state_for_object_with_unknown_value
81
+ @object.state = 'invalid'
82
+ exception = assert_raise(ArgumentError) { @states.match!(@object) }
83
+ assert_equal '"invalid" is not a known state value', exception.message
84
+ end
85
+ end
86
+
87
+ class StateCollectionWithNamespaceTest < Test::Unit::TestCase
88
+ def setup
89
+ @klass = Class.new
90
+ @machine = StateMachine::Machine.new(@klass, :namespace => 'vehicle')
91
+ @states = StateMachine::StateCollection.new(@machine)
92
+
93
+ @states << @state = StateMachine::State.new(@machine, :parked)
94
+ @machine.states.concat(@states)
95
+ end
96
+
97
+ def test_should_index_by_name
98
+ assert_equal @state, @states[:parked, :name]
99
+ end
100
+
101
+ def test_should_index_by_qualified_name
102
+ assert_equal @state, @states[:vehicle_parked, :qualified_name]
103
+ end
104
+ end
105
+
106
+ class StateCollectionWithCustomStateValuesTest < Test::Unit::TestCase
107
+ def setup
108
+ @klass = Class.new
109
+ @machine = StateMachine::Machine.new(@klass)
110
+ @states = StateMachine::StateCollection.new(@machine)
111
+
112
+ @states << @state = StateMachine::State.new(@machine, :parked, :value => 1)
113
+ @machine.states.concat(@states)
114
+
115
+ @object = @klass.new
116
+ @object.state = 1
117
+ end
118
+
119
+ def test_should_match_if_value_matches
120
+ assert @states.matches?(@object, :parked)
121
+ end
122
+
123
+ def test_should_not_match_if_value_does_not_match
124
+ @object.state = 2
125
+ assert !@states.matches?(@object, :parked)
126
+ end
127
+
128
+ def test_should_find_state_for_object_if_value_is_known
129
+ assert_equal @state, @states.match(@object)
130
+ end
131
+ end
132
+
133
+ class StateCollectionWithStateMatchersTest < Test::Unit::TestCase
134
+ def setup
135
+ @klass = Class.new
136
+ @machine = StateMachine::Machine.new(@klass)
137
+ @states = StateMachine::StateCollection.new(@machine)
138
+
139
+ @states << @state = StateMachine::State.new(@machine, :parked, :if => lambda {|value| !value.nil?})
140
+ @machine.states.concat(@states)
141
+
142
+ @object = @klass.new
143
+ @object.state = 1
144
+ end
145
+
146
+ def test_should_match_if_value_matches
147
+ assert @states.matches?(@object, :parked)
148
+ end
149
+
150
+ def test_should_not_match_if_value_does_not_match
151
+ @object.state = nil
152
+ assert !@states.matches?(@object, :parked)
153
+ end
154
+
155
+ def test_should_find_state_for_object_if_value_is_known
156
+ assert_equal @state, @states.match(@object)
157
+ end
158
+ end
159
+
160
+ class StateCollectionWithInitialStateTest < Test::Unit::TestCase
161
+ def setup
162
+ @machine = StateMachine::Machine.new(Class.new)
163
+ @states = StateMachine::StateCollection.new(@machine)
164
+
165
+ @states << @parked = StateMachine::State.new(@machine, :parked)
166
+ @states << @idling = StateMachine::State.new(@machine, :idling)
167
+ @machine.states.concat(@states)
168
+
169
+ @parked.initial = true
170
+ end
171
+
172
+ def test_should_order_state_before_transition_states
173
+ @machine.event :ignite do
174
+ transition :to => :idling
175
+ end
176
+ assert_equal [@parked, @idling], @states.by_priority
177
+ end
178
+
179
+ def test_should_order_state_before_states_with_behaviors
180
+ @idling.context do
181
+ def speed
182
+ 0
183
+ end
184
+ end
185
+ assert_equal [@parked, @idling], @states.by_priority
186
+ end
187
+
188
+ def test_should_order_state_before_other_states
189
+ assert_equal [@parked, @idling], @states.by_priority
190
+ end
191
+
192
+ def test_should_order_state_before_callback_states
193
+ @machine.before_transition :from => :idling, :do => lambda {}
194
+ assert_equal [@parked, @idling], @states.by_priority
195
+ end
196
+ end
197
+
198
+ class StateCollectionWithStateBehaviorsTest < Test::Unit::TestCase
199
+ def setup
200
+ @machine = StateMachine::Machine.new(Class.new)
201
+ @states = StateMachine::StateCollection.new(@machine)
202
+
203
+ @states << @parked = StateMachine::State.new(@machine, :parked)
204
+ @states << @idling = StateMachine::State.new(@machine, :idling)
205
+ @machine.states.concat(@states)
206
+
207
+ @idling.context do
208
+ def speed
209
+ 0
210
+ end
211
+ end
212
+ end
213
+
214
+ def test_should_order_states_after_initial_state
215
+ @parked.initial = true
216
+ assert_equal [@parked, @idling], @states.by_priority
217
+ end
218
+
219
+ def test_should_order_states_after_transition_states
220
+ @machine.event :ignite do
221
+ transition :from => :parked
222
+ end
223
+ assert_equal [@parked, @idling], @states.by_priority
224
+ end
225
+
226
+ def test_should_order_states_before_other_states
227
+ assert_equal [@idling, @parked], @states.by_priority
228
+ end
229
+
230
+ def test_should_order_state_before_callback_states
231
+ @machine.before_transition :from => :parked, :do => lambda {}
232
+ assert_equal [@idling, @parked], @states.by_priority
233
+ end
234
+ end
235
+
236
+ class StateCollectionWithEventTransitionsTest < Test::Unit::TestCase
237
+ def setup
238
+ @machine = StateMachine::Machine.new(Class.new)
239
+ @states = StateMachine::StateCollection.new(@machine)
240
+
241
+ @states << @parked = StateMachine::State.new(@machine, :parked)
242
+ @states << @idling = StateMachine::State.new(@machine, :idling)
243
+ @machine.states.concat(@states)
244
+
245
+ @machine.event :ignite do
246
+ transition :to => :idling
247
+ end
248
+ end
249
+
250
+ def test_should_order_states_after_initial_state
251
+ @parked.initial = true
252
+ assert_equal [@parked, @idling], @states.by_priority
253
+ end
254
+
255
+ def test_should_order_states_before_states_with_behaviors
256
+ @parked.context do
257
+ def speed
258
+ 0
259
+ end
260
+ end
261
+ assert_equal [@idling, @parked], @states.by_priority
262
+ end
263
+
264
+ def test_should_order_states_before_other_states
265
+ assert_equal [@idling, @parked], @states.by_priority
266
+ end
267
+
268
+ def test_should_order_state_before_callback_states
269
+ @machine.before_transition :from => :parked, :do => lambda {}
270
+ assert_equal [@idling, @parked], @states.by_priority
271
+ end
272
+ end
273
+
274
+ class StateCollectionWithTransitionCallbacksTest < Test::Unit::TestCase
275
+ def setup
276
+ @machine = StateMachine::Machine.new(Class.new)
277
+ @states = StateMachine::StateCollection.new(@machine)
278
+
279
+ @states << @parked = StateMachine::State.new(@machine, :parked)
280
+ @states << @idling = StateMachine::State.new(@machine, :idling)
281
+ @machine.states.concat(@states)
282
+
283
+ @machine.before_transition :to => :idling, :do => lambda {}
284
+ end
285
+
286
+ def test_should_order_states_after_initial_state
287
+ @parked.initial = true
288
+ assert_equal [@parked, @idling], @states.by_priority
289
+ end
290
+
291
+ def test_should_order_states_after_transition_states
292
+ @machine.event :ignite do
293
+ transition :from => :parked
294
+ end
295
+ assert_equal [@parked, @idling], @states.by_priority
296
+ end
297
+
298
+ def test_should_order_states_after_states_with_behaviors
299
+ @parked.context do
300
+ def speed
301
+ 0
302
+ end
303
+ end
304
+ assert_equal [@parked, @idling], @states.by_priority
305
+ end
306
+
307
+ def test_should_order_states_after_other_states
308
+ assert_equal [@parked, @idling], @states.by_priority
309
+ end
310
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class StateMachineByDefaultTest < Test::Unit::TestCase
4
+ def setup
5
+ @klass = Class.new
6
+ @machine = @klass.state_machine
7
+ end
8
+
9
+ def test_should_use_state_attribute
10
+ assert_equal :state, @machine.attribute
11
+ end
12
+ end
13
+
14
+ class StateMachineTest < Test::Unit::TestCase
15
+ def setup
16
+ @klass = Class.new
17
+ end
18
+
19
+ def test_should_allow_state_machines_on_any_class
20
+ assert @klass.respond_to?(:state_machine)
21
+ end
22
+
23
+ def test_should_evaluate_block_within_machine_context
24
+ responded = false
25
+ @klass.state_machine(:state) do
26
+ responded = respond_to?(:event)
27
+ end
28
+
29
+ assert responded
30
+ end
31
+ end
@@ -0,0 +1,924 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class StateByDefaultTest < Test::Unit::TestCase
4
+ def setup
5
+ @machine = StateMachine::Machine.new(Class.new)
6
+ @machine.states << @state = StateMachine::State.new(@machine, :parked)
7
+ end
8
+
9
+ def test_should_have_a_machine
10
+ assert_equal @machine, @state.machine
11
+ end
12
+
13
+ def test_should_have_a_name
14
+ assert_equal :parked, @state.name
15
+ end
16
+
17
+ def test_should_have_a_qualified_name
18
+ assert_equal :parked, @state.name
19
+ end
20
+
21
+ def test_should_have_a_human_name
22
+ assert_equal 'parked', @state.human_name
23
+ end
24
+
25
+ def test_should_use_stringify_the_name_as_the_value
26
+ assert_equal 'parked', @state.value
27
+ end
28
+
29
+ def test_should_not_be_initial
30
+ assert !@state.initial
31
+ end
32
+
33
+ def test_should_not_have_a_matcher
34
+ assert_nil @state.matcher
35
+ end
36
+
37
+ def test_should_not_have_any_methods
38
+ expected = {}
39
+ assert_equal expected, @state.methods
40
+ end
41
+ end
42
+
43
+ class StateTest < Test::Unit::TestCase
44
+ def setup
45
+ @machine = StateMachine::Machine.new(Class.new)
46
+ @machine.states << @state = StateMachine::State.new(@machine, :parked)
47
+ end
48
+
49
+ def test_should_raise_exception_if_invalid_option_specified
50
+ exception = assert_raise(ArgumentError) {StateMachine::State.new(@machine, :parked, :invalid => true)}
51
+ assert_equal 'Invalid key(s): invalid', exception.message
52
+ end
53
+
54
+ def test_should_allow_changing_machine
55
+ new_machine = StateMachine::Machine.new(Class.new)
56
+ @state.machine = new_machine
57
+ assert_equal new_machine, @state.machine
58
+ end
59
+
60
+ def test_should_allow_changing_value
61
+ @state.value = 1
62
+ assert_equal 1, @state.value
63
+ end
64
+
65
+ def test_should_allow_changing_initial
66
+ @state.initial = true
67
+ assert @state.initial
68
+ end
69
+
70
+ def test_should_allow_changing_matcher
71
+ matcher = lambda {}
72
+ @state.matcher = matcher
73
+ assert_equal matcher, @state.matcher
74
+ end
75
+
76
+ def test_should_allow_changing_human_name
77
+ @state.human_name = 'stopped'
78
+ assert_equal 'stopped', @state.human_name
79
+ end
80
+
81
+ def test_should_use_pretty_inspect
82
+ assert_equal '#<StateMachine::State name=:parked value="parked" initial=false context=[]>', @state.inspect
83
+ end
84
+ end
85
+
86
+ class StateWithoutNameTest < Test::Unit::TestCase
87
+ def setup
88
+ @klass = Class.new
89
+ @machine = StateMachine::Machine.new(@klass)
90
+ @machine.states << @state = StateMachine::State.new(@machine, nil)
91
+ end
92
+
93
+ def test_should_have_a_nil_name
94
+ assert_nil @state.name
95
+ end
96
+
97
+ def test_should_have_a_nil_qualified_name
98
+ assert_nil @state.qualified_name
99
+ end
100
+
101
+ def test_should_have_an_empty_human_name
102
+ assert_equal 'nil', @state.human_name
103
+ end
104
+
105
+ def test_should_have_a_nil_value
106
+ assert_nil @state.value
107
+ end
108
+
109
+ def test_should_not_redefine_nil_predicate
110
+ object = @klass.new
111
+ assert !object.nil?
112
+ assert !object.respond_to?('?')
113
+ end
114
+
115
+ def test_should_have_a_description
116
+ assert_equal 'nil', @state.description
117
+ end
118
+ end
119
+
120
+ class StateWithNameTest < Test::Unit::TestCase
121
+ def setup
122
+ @klass = Class.new
123
+ @machine = StateMachine::Machine.new(@klass)
124
+ @machine.states << @state = StateMachine::State.new(@machine, :parked)
125
+ end
126
+
127
+ def test_should_have_a_name
128
+ assert_equal :parked, @state.name
129
+ end
130
+
131
+ def test_should_have_a_qualified_name
132
+ assert_equal :parked, @state.name
133
+ end
134
+
135
+ def test_should_have_a_human_name
136
+ assert_equal 'parked', @state.human_name
137
+ end
138
+
139
+ def test_should_use_stringify_the_name_as_the_value
140
+ assert_equal 'parked', @state.value
141
+ end
142
+
143
+ def test_should_match_stringified_name
144
+ assert @state.matches?('parked')
145
+ assert !@state.matches?('idling')
146
+ end
147
+
148
+ def test_should_not_include_value_in_description
149
+ assert_equal 'parked', @state.description
150
+ end
151
+
152
+ def test_should_define_predicate
153
+ assert @klass.new.respond_to?(:parked?)
154
+ end
155
+ end
156
+
157
+ class StateWithNilValueTest < Test::Unit::TestCase
158
+ def setup
159
+ @klass = Class.new
160
+ @machine = StateMachine::Machine.new(@klass)
161
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => nil)
162
+ end
163
+
164
+ def test_should_have_a_name
165
+ assert_equal :parked, @state.name
166
+ end
167
+
168
+ def test_should_have_a_nil_value
169
+ assert_nil @state.value
170
+ end
171
+
172
+ def test_should_match_nil_values
173
+ assert @state.matches?(nil)
174
+ end
175
+
176
+ def test_should_have_a_description
177
+ assert_equal 'parked (nil)', @state.description
178
+ end
179
+
180
+ def test_should_define_predicate
181
+ object = @klass.new
182
+ assert object.respond_to?(:parked?)
183
+ end
184
+ end
185
+
186
+ class StateWithSymbolicValueTest < Test::Unit::TestCase
187
+ def setup
188
+ @klass = Class.new
189
+ @machine = StateMachine::Machine.new(@klass)
190
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => :parked)
191
+ end
192
+
193
+ def test_should_use_custom_value
194
+ assert_equal :parked, @state.value
195
+ end
196
+
197
+ def test_should_not_include_value_in_description
198
+ assert_equal 'parked', @state.description
199
+ end
200
+
201
+ def test_should_match_symbolic_value
202
+ assert @state.matches?(:parked)
203
+ assert !@state.matches?('parked')
204
+ end
205
+
206
+ def test_should_define_predicate
207
+ object = @klass.new
208
+ assert object.respond_to?(:parked?)
209
+ end
210
+ end
211
+
212
+ class StateWithIntegerValueTest < Test::Unit::TestCase
213
+ def setup
214
+ @klass = Class.new
215
+ @machine = StateMachine::Machine.new(@klass)
216
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => 1)
217
+ end
218
+
219
+ def test_should_use_custom_value
220
+ assert_equal 1, @state.value
221
+ end
222
+
223
+ def test_should_include_value_in_description
224
+ assert_equal 'parked (1)', @state.description
225
+ end
226
+
227
+ def test_should_match_integer_value
228
+ assert @state.matches?(1)
229
+ assert !@state.matches?(2)
230
+ end
231
+
232
+ def test_should_define_predicate
233
+ object = @klass.new
234
+ assert object.respond_to?(:parked?)
235
+ end
236
+ end
237
+
238
+ class StateWithLambdaValueTest < Test::Unit::TestCase
239
+ def setup
240
+ @klass = Class.new
241
+ @args = nil
242
+ @machine = StateMachine::Machine.new(@klass)
243
+ @value = lambda {|*args| @args = args; :parked}
244
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => @value)
245
+ end
246
+
247
+ def test_should_use_evaluated_value_by_default
248
+ assert_equal :parked, @state.value
249
+ end
250
+
251
+ def test_should_allow_access_to_original_value
252
+ assert_equal @value, @state.value(false)
253
+ end
254
+
255
+ def test_should_include_masked_value_in_description
256
+ assert_equal 'parked (*)', @state.description
257
+ end
258
+
259
+ def test_should_not_pass_in_any_arguments
260
+ @state.value
261
+ assert_equal [], @args
262
+ end
263
+
264
+ def test_should_define_predicate
265
+ object = @klass.new
266
+ assert object.respond_to?(:parked?)
267
+ end
268
+
269
+ def test_should_match_evaluated_value
270
+ assert @state.matches?(:parked)
271
+ end
272
+ end
273
+
274
+ class StateWithCachedLambdaValueTest < Test::Unit::TestCase
275
+ def setup
276
+ @klass = Class.new
277
+ @machine = StateMachine::Machine.new(@klass)
278
+ @dynamic_value = lambda {'value'}
279
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => @dynamic_value, :cache => true)
280
+ end
281
+
282
+ def test_should_be_caching
283
+ assert @state.cache
284
+ end
285
+
286
+ def test_should_evaluate_value
287
+ assert_equal 'value', @state.value
288
+ end
289
+
290
+ def test_should_only_evaluate_value_once
291
+ value = @state.value
292
+ assert_same value, @state.value
293
+ end
294
+
295
+ def test_should_update_value_index_for_state_collection
296
+ @state.value
297
+ assert_equal @state, @machine.states['value', :value]
298
+ assert_nil @machine.states[@dynamic_value, :value]
299
+ end
300
+ end
301
+
302
+ class StateWithoutCachedLambdaValueTest < Test::Unit::TestCase
303
+ def setup
304
+ @klass = Class.new
305
+ @machine = StateMachine::Machine.new(@klass)
306
+ @dynamic_value = lambda {'value'}
307
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => @dynamic_value)
308
+ end
309
+
310
+ def test_should_not_be_caching
311
+ assert !@state.cache
312
+ end
313
+
314
+ def test_should_evaluate_value_each_time
315
+ value = @state.value
316
+ assert_not_same value, @state.value
317
+ end
318
+
319
+ def test_should_not_update_value_index_for_state_collection
320
+ @state.value
321
+ assert_nil @machine.states['value', :value]
322
+ assert_equal @state, @machine.states[@dynamic_value, :value]
323
+ end
324
+ end
325
+
326
+ class StateWithMatcherTest < Test::Unit::TestCase
327
+ def setup
328
+ @klass = Class.new
329
+ @args = nil
330
+ @machine = StateMachine::Machine.new(@klass)
331
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :if => lambda {|value| value == 1})
332
+ end
333
+
334
+ def test_should_not_match_actual_value
335
+ assert !@state.matches?('parked')
336
+ end
337
+
338
+ def test_should_match_evaluated_block
339
+ assert @state.matches?(1)
340
+ end
341
+ end
342
+
343
+ class StateWithHumanNameTest < Test::Unit::TestCase
344
+ def setup
345
+ @klass = Class.new
346
+ @machine = StateMachine::Machine.new(@klass)
347
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :human_name => 'stopped')
348
+ end
349
+
350
+ def test_should_use_custom_human_name
351
+ assert_equal 'stopped', @state.human_name
352
+ end
353
+ end
354
+
355
+ class StateWithDynamicHumanNameTest < Test::Unit::TestCase
356
+ def setup
357
+ @klass = Class.new
358
+ @machine = StateMachine::Machine.new(@klass)
359
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :human_name => lambda {|state, object| ['stopped', object]})
360
+ end
361
+
362
+ def test_should_use_custom_human_name
363
+ human_name, klass = @state.human_name
364
+ assert_equal 'stopped', human_name
365
+ assert_equal @klass, klass
366
+ end
367
+
368
+ def test_should_allow_custom_class_to_be_passed_through
369
+ human_name, klass = @state.human_name(1)
370
+ assert_equal 'stopped', human_name
371
+ assert_equal 1, klass
372
+ end
373
+
374
+ def test_should_not_cache_value
375
+ assert_not_same @state.human_name, @state.human_name
376
+ end
377
+ end
378
+
379
+ class StateInitialTest < Test::Unit::TestCase
380
+ def setup
381
+ @machine = StateMachine::Machine.new(Class.new)
382
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :initial => true)
383
+ end
384
+
385
+ def test_should_be_initial
386
+ assert @state.initial
387
+ assert @state.initial?
388
+ end
389
+ end
390
+
391
+ class StateNotInitialTest < Test::Unit::TestCase
392
+ def setup
393
+ @machine = StateMachine::Machine.new(Class.new)
394
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :initial => false)
395
+ end
396
+
397
+ def test_should_not_be_initial
398
+ assert !@state.initial
399
+ assert !@state.initial?
400
+ end
401
+ end
402
+
403
+ class StateFinalTest < Test::Unit::TestCase
404
+ def setup
405
+ @machine = StateMachine::Machine.new(Class.new)
406
+ @machine.states << @state = StateMachine::State.new(@machine, :parked)
407
+ end
408
+
409
+ def test_should_be_final_without_input_transitions
410
+ assert @state.final?
411
+ end
412
+
413
+ def test_should_be_final_with_input_transitions
414
+ @machine.event :park do
415
+ transition :idling => :parked
416
+ end
417
+
418
+ assert @state.final?
419
+ end
420
+
421
+ def test_should_be_final_with_loopback
422
+ @machine.event :ignite do
423
+ transition :parked => same
424
+ end
425
+
426
+ assert @state.final?
427
+ end
428
+ end
429
+
430
+ class StateNotFinalTest < Test::Unit::TestCase
431
+ def setup
432
+ @machine = StateMachine::Machine.new(Class.new)
433
+ @machine.states << @state = StateMachine::State.new(@machine, :parked)
434
+ end
435
+
436
+ def test_should_not_be_final_with_outgoing_whitelist_transitions
437
+ @machine.event :ignite do
438
+ transition :parked => :idling
439
+ end
440
+
441
+ assert !@state.final?
442
+ end
443
+
444
+ def test_should_not_be_final_with_outgoing_all_transitions
445
+ @machine.event :ignite do
446
+ transition all => :idling
447
+ end
448
+
449
+ assert !@state.final?
450
+ end
451
+
452
+ def test_should_not_be_final_with_outgoing_blacklist_transitions
453
+ @machine.event :ignite do
454
+ transition all - :first_gear => :idling
455
+ end
456
+
457
+ assert !@state.final?
458
+ end
459
+ end
460
+
461
+ class StateWithConflictingHelpersBeforeDefinitionTest < Test::Unit::TestCase
462
+ def setup
463
+ require 'stringio'
464
+ @original_stderr, $stderr = $stderr, StringIO.new
465
+
466
+ @superclass = Class.new do
467
+ def parked?
468
+ 0
469
+ end
470
+ end
471
+ @klass = Class.new(@superclass)
472
+ @machine = StateMachine::Machine.new(@klass)
473
+ @machine.state :parked
474
+ @object = @klass.new
475
+ end
476
+
477
+ def test_should_not_override_state_predicate
478
+ assert_equal 0, @object.parked?
479
+ end
480
+
481
+ def test_should_output_warning
482
+ assert_equal "Instance method \"parked?\" is already defined in #{@superclass.to_s}, use generic helper instead.\n", $stderr.string
483
+ end
484
+
485
+ def teardown
486
+ $stderr = @original_stderr
487
+ end
488
+ end
489
+
490
+ class StateWithConflictingHelpersAfterDefinitionTest < Test::Unit::TestCase
491
+ def setup
492
+ require 'stringio'
493
+ @original_stderr, $stderr = $stderr, StringIO.new
494
+
495
+ @klass = Class.new do
496
+ def parked?
497
+ 0
498
+ end
499
+ end
500
+ @machine = StateMachine::Machine.new(@klass)
501
+ @machine.state :parked
502
+ @object = @klass.new
503
+ end
504
+
505
+ def test_should_not_override_state_predicate
506
+ assert_equal 0, @object.parked?
507
+ end
508
+
509
+ def test_should_still_allow_super_chaining
510
+ @klass.class_eval do
511
+ def parked?
512
+ super
513
+ end
514
+ end
515
+
516
+ assert_equal false, @object.parked?
517
+ end
518
+
519
+ def test_should_not_output_warning
520
+ assert_equal '', $stderr.string
521
+ end
522
+
523
+ def teardown
524
+ $stderr = @original_stderr
525
+ end
526
+ end
527
+
528
+ class StateWithConflictingMachineTest < Test::Unit::TestCase
529
+ def setup
530
+ require 'stringio'
531
+ @original_stderr, $stderr = $stderr, StringIO.new
532
+
533
+ @klass = Class.new
534
+ @state_machine = StateMachine::Machine.new(@klass, :state)
535
+ @state_machine.states << @state = StateMachine::State.new(@state_machine, :parked)
536
+ end
537
+
538
+ def test_should_output_warning_if_using_different_attribute
539
+ @status_machine = StateMachine::Machine.new(@klass, :status)
540
+ @status_machine.states << @state = StateMachine::State.new(@status_machine, :parked)
541
+
542
+ assert_equal "State :parked for :status is already defined in :state\n", $stderr.string
543
+ end
544
+
545
+ def test_should_not_output_warning_if_using_same_attribute
546
+ @status_machine = StateMachine::Machine.new(@klass, :status, :attribute => :state)
547
+ @status_machine.states << @state = StateMachine::State.new(@status_machine, :parked)
548
+
549
+ assert_equal '', $stderr.string
550
+ end
551
+
552
+ def test_should_not_output_warning_if_using_different_namespace
553
+ @status_machine = StateMachine::Machine.new(@klass, :status, :namespace => 'alarm')
554
+ @status_machine.states << @state = StateMachine::State.new(@status_machine, :parked)
555
+
556
+ assert_equal '', $stderr.string
557
+ end
558
+
559
+ def teardown
560
+ $stderr = @original_stderr
561
+ end
562
+ end
563
+
564
+ class StateWithNamespaceTest < Test::Unit::TestCase
565
+ def setup
566
+ @klass = Class.new
567
+ @machine = StateMachine::Machine.new(@klass, :namespace => 'alarm')
568
+ @machine.states << @state = StateMachine::State.new(@machine, :active)
569
+ @object = @klass.new
570
+ end
571
+
572
+ def test_should_have_a_name
573
+ assert_equal :active, @state.name
574
+ end
575
+
576
+ def test_should_have_a_qualified_name
577
+ assert_equal :alarm_active, @state.qualified_name
578
+ end
579
+
580
+ def test_should_namespace_predicate
581
+ assert @object.respond_to?(:alarm_active?)
582
+ end
583
+ end
584
+
585
+ class StateAfterBeingCopiedTest < Test::Unit::TestCase
586
+ def setup
587
+ @machine = StateMachine::Machine.new(Class.new)
588
+ @machine.states << @state = StateMachine::State.new(@machine, :parked)
589
+ @copied_state = @state.dup
590
+ end
591
+
592
+ def test_should_not_have_the_same_collection_of_methods
593
+ assert_not_same @state.methods, @copied_state.methods
594
+ end
595
+ end
596
+
597
+ class StateWithContextTest < Test::Unit::TestCase
598
+ def setup
599
+ @klass = Class.new
600
+ @machine = StateMachine::Machine.new(@klass)
601
+ @ancestors = @klass.ancestors
602
+ @machine.states << @state = StateMachine::State.new(@machine, :idling)
603
+
604
+ speed_method = nil
605
+ rpm_method = nil
606
+ @state.context do
607
+ def speed
608
+ 0
609
+ end
610
+ speed_method = instance_method(:speed)
611
+
612
+ def rpm
613
+ 1000
614
+ end
615
+ rpm_method = instance_method(:rpm)
616
+ end
617
+
618
+ @speed_method = speed_method
619
+ @rpm_method = rpm_method
620
+ end
621
+
622
+ def test_should_include_new_module_in_owner_class
623
+ assert_not_equal @ancestors, @klass.ancestors
624
+ assert_equal 1, @klass.ancestors.size - @ancestors.size
625
+ end
626
+
627
+ def test_should_define_each_context_method_in_owner_class
628
+ %w(speed rpm).each {|method| assert @klass.method_defined?(method)}
629
+ end
630
+
631
+ def test_should_not_use_context_methods_as_owner_class_methods
632
+ assert_not_equal @speed_method, @klass.instance_method(:speed)
633
+ assert_not_equal @rpm_method, @klass.instance_method(:rpm)
634
+ end
635
+
636
+ def test_should_include_context_methods_in_state_methods
637
+ assert_equal @speed_method, @state.methods[:speed]
638
+ assert_equal @rpm_method, @state.methods[:rpm]
639
+ end
640
+ end
641
+
642
+ class StateWithMultipleContextsTest < Test::Unit::TestCase
643
+ def setup
644
+ @klass = Class.new
645
+ @machine = StateMachine::Machine.new(@klass)
646
+ @ancestors = @klass.ancestors
647
+ @machine.states << @state = StateMachine::State.new(@machine, :idling)
648
+
649
+ speed_method = nil
650
+ @state.context do
651
+ def speed
652
+ 0
653
+ end
654
+
655
+ speed_method = instance_method(:speed)
656
+ end
657
+ @speed_method = speed_method
658
+
659
+ rpm_method = nil
660
+ @state.context do
661
+ def rpm
662
+ 1000
663
+ end
664
+
665
+ rpm_method = instance_method(:rpm)
666
+ end
667
+ @rpm_method = rpm_method
668
+ end
669
+
670
+ def test_should_include_new_module_in_owner_class
671
+ assert_not_equal @ancestors, @klass.ancestors
672
+ assert_equal 2, @klass.ancestors.size - @ancestors.size
673
+ end
674
+
675
+ def test_should_define_each_context_method_in_owner_class
676
+ %w(speed rpm).each {|method| assert @klass.method_defined?(method)}
677
+ end
678
+
679
+ def test_should_not_use_context_methods_as_owner_class_methods
680
+ assert_not_equal @speed_method, @klass.instance_method(:speed)
681
+ assert_not_equal @rpm_method, @klass.instance_method(:rpm)
682
+ end
683
+
684
+ def test_should_include_context_methods_in_state_methods
685
+ assert_equal @speed_method, @state.methods[:speed]
686
+ assert_equal @rpm_method, @state.methods[:rpm]
687
+ end
688
+ end
689
+
690
+ class StateWithExistingContextMethodTest < Test::Unit::TestCase
691
+ def setup
692
+ @klass = Class.new do
693
+ def speed
694
+ 60
695
+ end
696
+ end
697
+ @original_speed_method = @klass.instance_method(:speed)
698
+
699
+ @machine = StateMachine::Machine.new(@klass)
700
+ @machine.states << @state = StateMachine::State.new(@machine, :idling)
701
+ @state.context do
702
+ def speed
703
+ 0
704
+ end
705
+ end
706
+ end
707
+
708
+ def test_should_not_override_method
709
+ assert_equal @original_speed_method, @klass.instance_method(:speed)
710
+ end
711
+ end
712
+
713
+ class StateWithRedefinedContextMethodTest < Test::Unit::TestCase
714
+ def setup
715
+ @klass = Class.new
716
+ @machine = StateMachine::Machine.new(@klass)
717
+ @machine.states << @state = StateMachine::State.new(@machine, 'on')
718
+
719
+ old_speed_method = nil
720
+ @state.context do
721
+ def speed
722
+ 0
723
+ end
724
+ old_speed_method = instance_method(:speed)
725
+ end
726
+ @old_speed_method = old_speed_method
727
+
728
+ current_speed_method = nil
729
+ @state.context do
730
+ def speed
731
+ 'green'
732
+ end
733
+ current_speed_method = instance_method(:speed)
734
+ end
735
+ @current_speed_method = current_speed_method
736
+ end
737
+
738
+ def test_should_track_latest_defined_method
739
+ assert_equal @current_speed_method, @state.methods[:speed]
740
+ end
741
+ end
742
+
743
+ class StateWithInvalidMethodCallTest < Test::Unit::TestCase
744
+ def setup
745
+ @klass = Class.new
746
+ @machine = StateMachine::Machine.new(@klass)
747
+ @ancestors = @klass.ancestors
748
+ @machine.states << @state = StateMachine::State.new(@machine, :idling)
749
+ @state.context do
750
+ def speed
751
+ 0
752
+ end
753
+ end
754
+
755
+ @object = @klass.new
756
+ end
757
+
758
+ def test_should_call_method_missing_arg
759
+ assert_equal 1, @state.call(@object, :invalid, lambda {1})
760
+ end
761
+ end
762
+
763
+ class StateWithValidMethodCallTest < Test::Unit::TestCase
764
+ def setup
765
+ @klass = Class.new
766
+ @machine = StateMachine::Machine.new(@klass)
767
+ @ancestors = @klass.ancestors
768
+ @machine.states << @state = StateMachine::State.new(@machine, :idling)
769
+ @state.context do
770
+ def speed(arg = nil)
771
+ block_given? ? [arg, yield] : arg
772
+ end
773
+ end
774
+
775
+ @object = @klass.new
776
+ end
777
+
778
+ def test_should_not_raise_an_exception
779
+ assert_nothing_raised { @state.call(@object, :speed, lambda {raise}) }
780
+ end
781
+
782
+ def test_should_pass_arguments_through
783
+ assert_equal 1, @state.call(@object, :speed, lambda {}, 1)
784
+ end
785
+
786
+ def test_should_pass_blocks_through
787
+ assert_equal [nil, 1], @state.call(@object, :speed) {1}
788
+ end
789
+
790
+ def test_should_pass_both_arguments_and_blocks_through
791
+ assert_equal [1, 2], @state.call(@object, :speed, lambda {}, 1) {2}
792
+ end
793
+ end
794
+
795
+ begin
796
+ # Load library
797
+ require 'rubygems'
798
+ gem 'ruby-graphviz', '>=0.9.0'
799
+ require 'graphviz'
800
+
801
+ class StateDrawingTest < Test::Unit::TestCase
802
+ def setup
803
+ @machine = StateMachine::Machine.new(Class.new)
804
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => 1)
805
+ @machine.event :ignite do
806
+ transition :parked => :idling
807
+ end
808
+
809
+ graph = GraphViz.new('G')
810
+ @node = @state.draw(graph)
811
+ end
812
+
813
+ def test_should_use_ellipse_shape
814
+ assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
815
+ end
816
+
817
+ def test_should_set_width_to_one
818
+ assert_equal '1', @node['width'].to_s.gsub('"', '')
819
+ end
820
+
821
+ def test_should_set_height_to_one
822
+ assert_equal '1', @node['height'].to_s.gsub('"', '')
823
+ end
824
+
825
+ def test_should_use_stringified_name_as_name
826
+ assert_equal 'parked', Gem::Version.new(Constants::RGV_VERSION) <= Gem::Version.new('0.9.11') ? @node.name : @node.id
827
+ end
828
+
829
+ def test_should_use_description_as_label
830
+ assert_equal 'parked (1)', @node['label'].to_s.gsub('"', '')
831
+ end
832
+ end
833
+
834
+ class StateDrawingInitialTest < Test::Unit::TestCase
835
+ def setup
836
+ @machine = StateMachine::Machine.new(Class.new)
837
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :initial => true)
838
+ @machine.event :ignite do
839
+ transition :parked => :idling
840
+ end
841
+
842
+ @graph = GraphViz.new('G')
843
+ @node = @state.draw(@graph)
844
+ end
845
+
846
+ def test_should_use_ellipse_as_shape
847
+ assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
848
+ end
849
+
850
+ def test_should_draw_edge_between_point_and_state
851
+ assert_equal 2, @graph.node_count
852
+ assert_equal 1, @graph.edge_count
853
+ end
854
+ end
855
+
856
+ class StateDrawingNilNameTest < Test::Unit::TestCase
857
+ def setup
858
+ @machine = StateMachine::Machine.new(Class.new)
859
+ @machine.states << @state = StateMachine::State.new(@machine, nil)
860
+
861
+ graph = GraphViz.new('G')
862
+ @node = @state.draw(graph)
863
+ end
864
+
865
+ def test_should_use_stringified_nil_as_name
866
+ assert_equal 'nil', Gem::Version.new(Constants::RGV_VERSION) <= Gem::Version.new('0.9.11') ? @node.name : @node.id
867
+ end
868
+
869
+ def test_should_use_description_as_label
870
+ assert_equal 'nil', @node['label'].to_s.gsub('"', '')
871
+ end
872
+ end
873
+
874
+ class StateDrawingLambdaValueTest < Test::Unit::TestCase
875
+ def setup
876
+ @machine = StateMachine::Machine.new(Class.new)
877
+ @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => lambda {})
878
+
879
+ graph = GraphViz.new('G')
880
+ @node = @state.draw(graph)
881
+ end
882
+
883
+ def test_should_use_stringified_name_as_name
884
+ assert_equal 'parked', Gem::Version.new(Constants::RGV_VERSION) <= Gem::Version.new('0.9.11') ? @node.name : @node.id
885
+ end
886
+
887
+ def test_should_use_description_as_label
888
+ assert_equal 'parked (*)', @node['label'].to_s.gsub('"', '')
889
+ end
890
+ end
891
+
892
+ class StateDrawingNonFinalTest < Test::Unit::TestCase
893
+ def setup
894
+ @machine = StateMachine::Machine.new(Class.new)
895
+ @machine.states << @state = StateMachine::State.new(@machine, :parked)
896
+ @machine.event :ignite do
897
+ transition :parked => :idling
898
+ end
899
+
900
+ graph = GraphViz.new('G')
901
+ @node = @state.draw(graph)
902
+ end
903
+
904
+ def test_should_use_ellipse_as_shape
905
+ assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
906
+ end
907
+ end
908
+
909
+ class StateDrawingFinalTest < Test::Unit::TestCase
910
+ def setup
911
+ @machine = StateMachine::Machine.new(Class.new)
912
+ @machine.states << @state = StateMachine::State.new(@machine, :parked)
913
+
914
+ graph = GraphViz.new('G')
915
+ @node = @state.draw(graph)
916
+ end
917
+
918
+ def test_should_use_doublecircle_as_shape
919
+ assert_equal 'doublecircle', @node['shape'].to_s.gsub('"', '')
920
+ end
921
+ end
922
+ rescue LoadError
923
+ $stderr.puts 'Skipping GraphViz StateMachine::State tests. `gem install ruby-graphviz` >= v0.9.0 and try again.'
924
+ end