hsume2-state_machine 1.0.1

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