state_machine 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. data/.gitignore +7 -11
  2. data/.travis.yml +49 -7
  3. data/Appraisals +255 -87
  4. data/CHANGELOG.md +30 -0
  5. data/README.md +142 -21
  6. data/Rakefile +1 -11
  7. data/examples/Gemfile +5 -0
  8. data/examples/Gemfile.lock +14 -0
  9. data/examples/auto_shop.rb +2 -0
  10. data/examples/car.rb +2 -0
  11. data/examples/doc/AutoShop.html +2856 -0
  12. data/examples/doc/AutoShop_state.png +0 -0
  13. data/examples/doc/Car.html +919 -0
  14. data/examples/doc/Car_state.png +0 -0
  15. data/examples/doc/TrafficLight.html +2230 -0
  16. data/examples/doc/TrafficLight_state.png +0 -0
  17. data/examples/doc/Vehicle.html +7921 -0
  18. data/examples/doc/Vehicle_state.png +0 -0
  19. data/examples/doc/_index.html +136 -0
  20. data/examples/doc/class_list.html +47 -0
  21. data/examples/doc/css/common.css +1 -0
  22. data/examples/doc/css/full_list.css +55 -0
  23. data/examples/doc/css/style.css +322 -0
  24. data/examples/doc/file_list.html +46 -0
  25. data/examples/doc/frames.html +13 -0
  26. data/examples/doc/index.html +136 -0
  27. data/examples/doc/js/app.js +205 -0
  28. data/examples/doc/js/full_list.js +173 -0
  29. data/examples/doc/js/jquery.js +16 -0
  30. data/examples/doc/method_list.html +734 -0
  31. data/examples/doc/top-level-namespace.html +105 -0
  32. data/examples/rails-rest/migration.rb +1 -5
  33. data/examples/rails-rest/view__form.html.erb +34 -0
  34. data/examples/rails-rest/view_edit.html.erb +2 -21
  35. data/examples/rails-rest/view_index.html.erb +6 -4
  36. data/examples/rails-rest/view_new.html.erb +2 -11
  37. data/examples/rails-rest/view_show.html.erb +5 -3
  38. data/examples/traffic_light.rb +2 -0
  39. data/examples/vehicle.rb +2 -0
  40. data/gemfiles/active_model-3.0.0.gemfile.lock +9 -6
  41. data/gemfiles/active_model-3.0.5.gemfile.lock +10 -7
  42. data/gemfiles/active_model-3.1.1.gemfile.lock +12 -10
  43. data/gemfiles/{active_model-3.2.0.gemfile → active_model-3.2.1.gemfile} +1 -1
  44. data/gemfiles/{graphviz-0.9.0.gemfile → active_model-3.2.12.gemfile} +1 -1
  45. data/gemfiles/active_model-3.2.12.gemfile.lock +36 -0
  46. data/gemfiles/{active_record-3.2.0.gemfile → active_model-3.2.13.rc1.gemfile} +1 -2
  47. data/gemfiles/active_model-3.2.13.rc1.gemfile.lock +36 -0
  48. data/gemfiles/active_model-4.0.0.gemfile +9 -0
  49. data/gemfiles/active_model-4.0.0.gemfile.lock +78 -0
  50. data/gemfiles/active_record-2.0.0.gemfile +2 -1
  51. data/gemfiles/active_record-2.0.0.gemfile.lock +15 -6
  52. data/gemfiles/active_record-2.0.5.gemfile +2 -1
  53. data/gemfiles/active_record-2.0.5.gemfile.lock +15 -6
  54. data/gemfiles/active_record-2.1.0.gemfile +2 -1
  55. data/gemfiles/active_record-2.1.0.gemfile.lock +15 -6
  56. data/gemfiles/active_record-2.1.2.gemfile +2 -1
  57. data/gemfiles/active_record-2.1.2.gemfile.lock +15 -6
  58. data/gemfiles/active_record-2.2.3.gemfile +2 -1
  59. data/gemfiles/active_record-2.2.3.gemfile.lock +15 -6
  60. data/gemfiles/active_record-2.3.12.gemfile +2 -1
  61. data/gemfiles/active_record-2.3.12.gemfile.lock +15 -6
  62. data/gemfiles/active_record-2.3.5.gemfile +9 -0
  63. data/gemfiles/active_record-2.3.5.gemfile.lock +39 -0
  64. data/gemfiles/active_record-3.0.0.gemfile +2 -1
  65. data/gemfiles/active_record-3.0.0.gemfile.lock +18 -11
  66. data/gemfiles/active_record-3.0.5.gemfile +2 -1
  67. data/gemfiles/active_record-3.0.5.gemfile.lock +19 -12
  68. data/gemfiles/active_record-3.1.1.gemfile +2 -1
  69. data/gemfiles/active_record-3.1.1.gemfile.lock +22 -16
  70. data/gemfiles/active_record-3.2.12.gemfile +9 -0
  71. data/gemfiles/active_record-3.2.12.gemfile.lock +51 -0
  72. data/gemfiles/active_record-3.2.13.rc1.gemfile +9 -0
  73. data/gemfiles/active_record-3.2.13.rc1.gemfile.lock +51 -0
  74. data/gemfiles/active_record-4.0.0.gemfile +11 -0
  75. data/gemfiles/active_record-4.0.0.gemfile.lock +83 -0
  76. data/gemfiles/data_mapper-0.10.2.gemfile +1 -0
  77. data/gemfiles/data_mapper-0.10.2.gemfile.lock +13 -9
  78. data/gemfiles/data_mapper-0.9.11.gemfile +1 -0
  79. data/gemfiles/data_mapper-0.9.11.gemfile.lock +31 -7
  80. data/gemfiles/data_mapper-0.9.4.gemfile.lock +25 -14
  81. data/gemfiles/data_mapper-0.9.7.gemfile +1 -0
  82. data/gemfiles/data_mapper-0.9.7.gemfile.lock +27 -15
  83. data/gemfiles/data_mapper-1.0.0.gemfile.lock +20 -17
  84. data/gemfiles/data_mapper-1.0.1.gemfile.lock +20 -17
  85. data/gemfiles/data_mapper-1.0.2.gemfile.lock +20 -17
  86. data/gemfiles/data_mapper-1.1.0.gemfile.lock +19 -16
  87. data/gemfiles/data_mapper-1.2.0.gemfile.lock +19 -16
  88. data/gemfiles/default.gemfile.lock +8 -5
  89. data/gemfiles/graphviz-0.9.17.gemfile +7 -0
  90. data/gemfiles/graphviz-0.9.17.gemfile.lock +29 -0
  91. data/gemfiles/graphviz-0.9.21.gemfile.lock +7 -4
  92. data/gemfiles/graphviz-1.0.0.gemfile.lock +7 -4
  93. data/gemfiles/graphviz-1.0.3.gemfile +7 -0
  94. data/gemfiles/graphviz-1.0.3.gemfile.lock +29 -0
  95. data/gemfiles/graphviz-1.0.8.gemfile +7 -0
  96. data/gemfiles/graphviz-1.0.8.gemfile.lock +29 -0
  97. data/gemfiles/mongo_mapper-0.10.0.gemfile +1 -0
  98. data/gemfiles/mongo_mapper-0.10.0.gemfile.lock +14 -11
  99. data/gemfiles/mongo_mapper-0.11.1.gemfile +7 -0
  100. data/gemfiles/mongo_mapper-0.11.1.gemfile.lock +44 -0
  101. data/gemfiles/mongo_mapper-0.11.2.gemfile +9 -0
  102. data/gemfiles/mongo_mapper-0.11.2.gemfile.lock +48 -0
  103. data/gemfiles/mongo_mapper-0.12.0.gemfile +9 -0
  104. data/gemfiles/mongo_mapper-0.12.0.gemfile.lock +48 -0
  105. data/gemfiles/mongo_mapper-0.5.5.gemfile.lock +7 -4
  106. data/gemfiles/mongo_mapper-0.5.8.gemfile.lock +7 -4
  107. data/gemfiles/mongo_mapper-0.6.0.gemfile.lock +7 -4
  108. data/gemfiles/mongo_mapper-0.6.10.gemfile.lock +7 -4
  109. data/gemfiles/mongo_mapper-0.7.0.gemfile.lock +7 -4
  110. data/gemfiles/mongo_mapper-0.7.5.gemfile.lock +7 -4
  111. data/gemfiles/mongo_mapper-0.8.0.gemfile.lock +7 -4
  112. data/gemfiles/mongo_mapper-0.8.3.gemfile.lock +7 -4
  113. data/gemfiles/mongo_mapper-0.8.4.gemfile.lock +7 -4
  114. data/gemfiles/mongo_mapper-0.8.6.gemfile.lock +7 -4
  115. data/gemfiles/mongo_mapper-0.9.0.gemfile.lock +7 -4
  116. data/gemfiles/mongoid-2.0.0.gemfile +2 -0
  117. data/gemfiles/mongoid-2.0.0.gemfile.lock +22 -18
  118. data/gemfiles/mongoid-2.1.4.gemfile +2 -0
  119. data/gemfiles/mongoid-2.1.4.gemfile.lock +21 -17
  120. data/gemfiles/mongoid-2.2.4.gemfile +2 -0
  121. data/gemfiles/mongoid-2.2.4.gemfile.lock +21 -17
  122. data/gemfiles/mongoid-2.3.3.gemfile +2 -0
  123. data/gemfiles/mongoid-2.3.3.gemfile.lock +21 -17
  124. data/gemfiles/mongoid-2.4.0.gemfile +9 -0
  125. data/gemfiles/mongoid-2.4.0.gemfile.lock +47 -0
  126. data/gemfiles/mongoid-2.4.10.gemfile +9 -0
  127. data/gemfiles/mongoid-2.4.10.gemfile.lock +47 -0
  128. data/gemfiles/mongoid-2.5.2.gemfile +9 -0
  129. data/gemfiles/mongoid-2.5.2.gemfile.lock +47 -0
  130. data/gemfiles/mongoid-2.6.0.gemfile +9 -0
  131. data/gemfiles/mongoid-2.6.0.gemfile.lock +47 -0
  132. data/gemfiles/mongoid-3.0.0.gemfile +8 -0
  133. data/gemfiles/mongoid-3.0.0.gemfile.lock +45 -0
  134. data/gemfiles/mongoid-3.0.22.gemfile +8 -0
  135. data/gemfiles/mongoid-3.0.22.gemfile.lock +45 -0
  136. data/gemfiles/mongoid-3.1.0.gemfile +8 -0
  137. data/gemfiles/mongoid-3.1.0.gemfile.lock +45 -0
  138. data/gemfiles/sequel-2.11.0.gemfile +2 -1
  139. data/gemfiles/sequel-2.11.0.gemfile.lock +11 -6
  140. data/gemfiles/sequel-2.12.0.gemfile +2 -1
  141. data/gemfiles/sequel-2.12.0.gemfile.lock +11 -6
  142. data/gemfiles/sequel-2.8.0.gemfile +2 -1
  143. data/gemfiles/sequel-2.8.0.gemfile.lock +11 -6
  144. data/gemfiles/sequel-3.0.0.gemfile +2 -1
  145. data/gemfiles/sequel-3.0.0.gemfile.lock +11 -6
  146. data/gemfiles/sequel-3.10.0.gemfile +9 -0
  147. data/gemfiles/sequel-3.10.0.gemfile.lock +33 -0
  148. data/gemfiles/sequel-3.13.0.gemfile +2 -1
  149. data/gemfiles/sequel-3.13.0.gemfile.lock +11 -6
  150. data/gemfiles/sequel-3.14.0.gemfile +2 -1
  151. data/gemfiles/sequel-3.14.0.gemfile.lock +11 -6
  152. data/gemfiles/sequel-3.23.0.gemfile +2 -1
  153. data/gemfiles/sequel-3.23.0.gemfile.lock +11 -6
  154. data/gemfiles/sequel-3.24.0.gemfile +2 -1
  155. data/gemfiles/sequel-3.24.0.gemfile.lock +11 -6
  156. data/gemfiles/sequel-3.29.0.gemfile +2 -1
  157. data/gemfiles/sequel-3.29.0.gemfile.lock +11 -6
  158. data/gemfiles/sequel-3.34.0.gemfile +9 -0
  159. data/gemfiles/sequel-3.34.0.gemfile.lock +33 -0
  160. data/gemfiles/sequel-3.35.0.gemfile +9 -0
  161. data/gemfiles/sequel-3.35.0.gemfile.lock +33 -0
  162. data/gemfiles/sequel-3.4.0.gemfile +9 -0
  163. data/gemfiles/sequel-3.4.0.gemfile.lock +33 -0
  164. data/gemfiles/sequel-3.44.0.gemfile +9 -0
  165. data/gemfiles/sequel-3.44.0.gemfile.lock +33 -0
  166. data/lib/state_machine.rb +6 -0
  167. data/lib/state_machine/branch.rb +9 -8
  168. data/lib/state_machine/callback.rb +2 -2
  169. data/lib/state_machine/core.rb +10 -0
  170. data/lib/state_machine/core_ext.rb +1 -0
  171. data/lib/state_machine/eval_helpers.rb +5 -3
  172. data/lib/state_machine/event.rb +17 -6
  173. data/lib/state_machine/graph.rb +92 -0
  174. data/lib/state_machine/integrations.rb +13 -1
  175. data/lib/state_machine/integrations/active_model.rb +14 -20
  176. data/lib/state_machine/integrations/active_model/observer.rb +3 -3
  177. data/lib/state_machine/integrations/active_model/observer_update.rb +42 -0
  178. data/lib/state_machine/integrations/active_record.rb +52 -25
  179. data/lib/state_machine/integrations/active_record/locale.rb +1 -1
  180. data/lib/state_machine/integrations/active_record/versions.rb +1 -17
  181. data/lib/state_machine/integrations/base.rb +15 -6
  182. data/lib/state_machine/integrations/data_mapper.rb +98 -35
  183. data/lib/state_machine/integrations/data_mapper/versions.rb +46 -8
  184. data/lib/state_machine/integrations/mongo_mapper.rb +39 -12
  185. data/lib/state_machine/integrations/mongo_mapper/locale.rb +1 -1
  186. data/lib/state_machine/integrations/mongo_mapper/versions.rb +3 -20
  187. data/lib/state_machine/integrations/mongoid.rb +52 -14
  188. data/lib/state_machine/integrations/mongoid/locale.rb +1 -1
  189. data/lib/state_machine/integrations/mongoid/versions.rb +52 -26
  190. data/lib/state_machine/integrations/sequel.rb +82 -33
  191. data/lib/state_machine/integrations/sequel/versions.rb +19 -44
  192. data/lib/state_machine/machine.rb +99 -59
  193. data/lib/state_machine/machine_collection.rb +1 -2
  194. data/lib/state_machine/macro_methods.rb +29 -0
  195. data/lib/state_machine/node_collection.rb +1 -1
  196. data/lib/state_machine/state.rb +18 -10
  197. data/lib/state_machine/state_context.rb +2 -2
  198. data/lib/state_machine/transition.rb +8 -1
  199. data/lib/state_machine/transition_collection.rb +2 -1
  200. data/lib/state_machine/version.rb +1 -1
  201. data/lib/state_machine/yard.rb +8 -0
  202. data/lib/state_machine/yard/handlers.rb +12 -0
  203. data/lib/state_machine/yard/handlers/base.rb +32 -0
  204. data/lib/state_machine/yard/handlers/event.rb +25 -0
  205. data/lib/state_machine/yard/handlers/machine.rb +344 -0
  206. data/lib/state_machine/yard/handlers/state.rb +25 -0
  207. data/lib/state_machine/yard/handlers/transition.rb +47 -0
  208. data/lib/state_machine/yard/templates.rb +3 -0
  209. data/lib/state_machine/yard/templates/default/class/html/setup.rb +30 -0
  210. data/lib/state_machine/yard/templates/default/class/html/state_machines.erb +12 -0
  211. data/lib/tasks/state_machine.rb +2 -1
  212. data/lib/yard-state_machine.rb +2 -0
  213. data/state_machine.gemspec +4 -3
  214. data/test/files/switch.rb +4 -0
  215. data/test/test_helper.rb +5 -0
  216. data/test/unit/branch_test.rb +117 -36
  217. data/test/unit/callback_test.rb +5 -2
  218. data/test/unit/eval_helpers_test.rb +49 -1
  219. data/test/unit/event_collection_test.rb +3 -1
  220. data/test/unit/event_test.rb +182 -12
  221. data/test/unit/graph_test.rb +98 -0
  222. data/test/unit/integrations/active_model_test.rb +82 -12
  223. data/test/unit/integrations/active_record_test.rb +393 -37
  224. data/test/unit/integrations/base_test.rb +7 -2
  225. data/test/unit/integrations/data_mapper_test.rb +326 -72
  226. data/test/unit/integrations/mongo_mapper_test.rb +338 -44
  227. data/test/unit/integrations/mongoid_test.rb +606 -98
  228. data/test/unit/integrations/sequel_test.rb +429 -102
  229. data/test/unit/integrations_test.rb +28 -6
  230. data/test/unit/machine_collection_test.rb +6 -2
  231. data/test/unit/machine_test.rb +134 -82
  232. data/test/unit/node_collection_test.rb +2 -2
  233. data/test/unit/path_test.rb +1 -1
  234. data/test/unit/state_test.rb +65 -21
  235. data/test/unit/transition_collection_test.rb +43 -23
  236. data/test/unit/transition_test.rb +8 -2
  237. metadata +303 -221
  238. data/gemfiles/active_model-3.2.0.gemfile.lock +0 -32
  239. data/gemfiles/active_record-3.2.0.gemfile.lock +0 -43
  240. data/gemfiles/graphviz-0.9.0.gemfile.lock +0 -26
@@ -2,7 +2,10 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
2
 
3
3
  class IntegrationMatcherTest < Test::Unit::TestCase
4
4
  def setup
5
- @klass = Class.new
5
+ superclass = Class.new
6
+ self.class.const_set('Vehicle', superclass)
7
+
8
+ @klass = Class.new(superclass)
6
9
  end
7
10
 
8
11
  def test_should_return_nil_if_no_match_found
@@ -13,20 +16,39 @@ class IntegrationMatcherTest < Test::Unit::TestCase
13
16
  integration = Module.new do
14
17
  include StateMachine::Integrations::Base
15
18
 
16
- def self.available?
17
- true
19
+ def self.matching_ancestors
20
+ ['IntegrationMatcherTest::Vehicle']
18
21
  end
22
+ end
23
+ StateMachine::Integrations.const_set('Custom', integration)
24
+
25
+ assert_equal integration, StateMachine::Integrations.match(@klass)
26
+ ensure
27
+ StateMachine::Integrations.send(:remove_const, 'Custom')
28
+ end
29
+
30
+ def test_should_return_nil_if_no_match_found_with_ancestors
31
+ assert_nil StateMachine::Integrations.match_ancestors(['IntegrationMatcherTest::Fake'])
32
+ end
33
+
34
+ def test_should_return_integration_class_if_match_found_with_ancestors
35
+ integration = Module.new do
36
+ include StateMachine::Integrations::Base
19
37
 
20
- def self.matches?(klass)
21
- true
38
+ def self.matching_ancestors
39
+ ['IntegrationMatcherTest::Vehicle']
22
40
  end
23
41
  end
24
42
  StateMachine::Integrations.const_set('Custom', integration)
25
43
 
26
- assert_equal integration, StateMachine::Integrations.match(@klass)
44
+ assert_equal integration, StateMachine::Integrations.match_ancestors(['IntegrationMatcherTest::Fake', 'IntegrationMatcherTest::Vehicle'])
27
45
  ensure
28
46
  StateMachine::Integrations.send(:remove_const, 'Custom')
29
47
  end
48
+
49
+ def teardown
50
+ self.class.send(:remove_const, 'Vehicle')
51
+ end
30
52
  end
31
53
 
32
54
  class IntegrationFinderTest < Test::Unit::TestCase
@@ -67,10 +67,10 @@ class MachineCollectionStateInitializationTest < Test::Unit::TestCase
67
67
  assert_equal 'active', @object.alarm_state
68
68
  end
69
69
 
70
- def test_should_initialize_existing_static_states_by_default
70
+ def test_should_not_initialize_existing_static_states_by_default
71
71
  @object.state = 'idling'
72
72
  @machines.initialize_states(@object)
73
- assert_equal 'parked', @object.state
73
+ assert_equal 'idling', @object.state
74
74
  end
75
75
 
76
76
  def test_should_initialize_existing_static_states_if_forced
@@ -164,6 +164,8 @@ class MachineCollectionFireTest < Test::Unit::TestCase
164
164
  end
165
165
 
166
166
  def test_should_run_failure_callbacks_if_any_event_cannot_transition
167
+ @state_failure_run = @alarm_state_failure_run = false
168
+
167
169
  @machines[:state].after_failure {@state_failure_run = true}
168
170
  @machines[:alarm_state].after_failure {@alarm_state_failure_run = true}
169
171
 
@@ -246,6 +248,7 @@ class MachineCollectionFireWithTransactionsTest < Test::Unit::TestCase
246
248
 
247
249
  def test_should_run_failure_callbacks_if_not_successful
248
250
  @object.allow_save = false
251
+ @state_failure_run = @alarm_state_failure_run = false
249
252
 
250
253
  @machines[:state].after_failure {@state_failure_run = true}
251
254
  @machines[:alarm_state].after_failure {@alarm_state_failure_run = true}
@@ -313,6 +316,7 @@ class MachineCollectionFireWithValidationsTest < Test::Unit::TestCase
313
316
  def test_should_run_failure_callbacks_if_no_transitions_exist
314
317
  @object.state = 'idling'
315
318
  @object.alarm_state = 'off'
319
+ @state_failure_run = @alarm_state_failure_run = false
316
320
 
317
321
  @machines[:state].after_failure {@state_failure_run = true}
318
322
  @machines[:alarm_state].after_failure {@alarm_state_failure_run = true}
@@ -170,7 +170,7 @@ class MachineByDefaultTest < Test::Unit::TestCase
170
170
  end
171
171
 
172
172
  def test_should_extend_owner_class_with_class_methods
173
- assert (class << @klass; ancestors; end).include?(StateMachine::ClassMethods)
173
+ assert((class << @klass; ancestors; end).include?(StateMachine::ClassMethods))
174
174
  end
175
175
 
176
176
  def test_should_include_instance_methods_in_owner_class
@@ -257,13 +257,12 @@ class MachineWithoutInitializationTest < Test::Unit::TestCase
257
257
  end
258
258
 
259
259
  def test_should_still_allow_manual_initialization
260
- @klass.class_eval do
260
+ @klass.send(:include, Module.new do
261
261
  def initialize(attributes = {})
262
- attributes.each {|attr, value| send("#{attr}=", value)}
263
262
  super()
264
263
  initialize_state_machines
265
264
  end
266
- end
265
+ end)
267
266
 
268
267
  object = @klass.new
269
268
  assert_equal 'parked', object.state
@@ -299,7 +298,7 @@ class MachineWithStaticInitialStateTest < Test::Unit::TestCase
299
298
  assert_equal 'parked', @klass.new.state
300
299
  end
301
300
 
302
- def test_should_still_set_initial_state_even_if_not_empty
301
+ def test_not_set_initial_state_even_if_not_empty
303
302
  @klass.class_eval do
304
303
  def initialize(attributes = {})
305
304
  self.state = 'idling'
@@ -307,7 +306,7 @@ class MachineWithStaticInitialStateTest < Test::Unit::TestCase
307
306
  end
308
307
  end
309
308
  object = @klass.new
310
- assert_equal 'parked', object.state
309
+ assert_equal 'idling', object.state
311
310
  end
312
311
 
313
312
  def test_should_set_initial_state_prior_to_initialization
@@ -319,7 +318,7 @@ class MachineWithStaticInitialStateTest < Test::Unit::TestCase
319
318
  end
320
319
  end
321
320
  klass = Class.new(base)
322
- machine = StateMachine::Machine.new(klass, :initial => :parked)
321
+ StateMachine::Machine.new(klass, :initial => :parked)
323
322
 
324
323
  assert_equal 'parked', klass.new.state_on_init
325
324
  end
@@ -438,7 +437,7 @@ class MachineStateInitializationTest < Test::Unit::TestCase
438
437
 
439
438
  def test_should_write_to_hash_if_specified
440
439
  @machine.initialize_state(@object, :to => hash = {})
441
- assert_equal expected = {'state' => 'parked'}, hash
440
+ assert_equal({'state' => 'parked'}, hash)
442
441
  end
443
442
 
444
443
  def test_should_not_write_to_object_if_writing_to_hash
@@ -511,61 +510,65 @@ class MachineWithCustomIntegrationTest < Test::Unit::TestCase
511
510
  integration = Module.new do
512
511
  include StateMachine::Integrations::Base
513
512
 
514
- def self.available?
515
- true
516
- end
517
-
518
- def self.matches?(klass)
519
- true
513
+ def self.matching_ancestors
514
+ ['MachineWithCustomIntegrationTest::Vehicle']
520
515
  end
521
516
  end
522
517
 
523
518
  StateMachine::Integrations.const_set('Custom', integration)
519
+
520
+ superclass = Class.new
521
+ self.class.const_set('Vehicle', superclass)
522
+
523
+ @klass = Class.new(superclass)
524
524
  end
525
525
 
526
526
  def test_should_be_extended_by_the_integration_if_explicit
527
- machine = StateMachine::Machine.new(Class.new, :integration => :custom)
528
- assert (class << machine; ancestors; end).include?(StateMachine::Integrations::Custom)
527
+ machine = StateMachine::Machine.new(@klass, :integration => :custom)
528
+ assert((class << machine; ancestors; end).include?(StateMachine::Integrations::Custom))
529
529
  end
530
530
 
531
531
  def test_should_not_be_extended_by_the_integration_if_implicit_but_not_available
532
532
  StateMachine::Integrations::Custom.class_eval do
533
- def self.available?
534
- false
533
+ class << self; remove_method :matching_ancestors; end
534
+ def self.matching_ancestors
535
+ []
535
536
  end
536
537
  end
537
538
 
538
- machine = StateMachine::Machine.new(Class.new)
539
- assert !(class << machine; ancestors; end).include?(StateMachine::Integrations::Custom)
539
+ machine = StateMachine::Machine.new(@klass)
540
+ assert(!(class << machine; ancestors; end).include?(StateMachine::Integrations::Custom))
540
541
  end
541
542
 
542
543
  def test_should_not_be_extended_by_the_integration_if_implicit_but_not_matched
543
544
  StateMachine::Integrations::Custom.class_eval do
544
- def self.matches?(klass)
545
- false
545
+ class << self; remove_method :matching_ancestors; end
546
+ def self.matching_ancestors
547
+ []
546
548
  end
547
549
  end
548
550
 
549
- machine = StateMachine::Machine.new(Class.new)
550
- assert !(class << machine; ancestors; end).include?(StateMachine::Integrations::Custom)
551
+ machine = StateMachine::Machine.new(@klass)
552
+ assert(!(class << machine; ancestors; end).include?(StateMachine::Integrations::Custom))
551
553
  end
552
554
 
553
555
  def test_should_be_extended_by_the_integration_if_implicit_and_available_and_matches
554
- machine = StateMachine::Machine.new(Class.new)
555
- assert (class << machine; ancestors; end).include?(StateMachine::Integrations::Custom)
556
+ machine = StateMachine::Machine.new(@klass)
557
+ assert((class << machine; ancestors; end).include?(StateMachine::Integrations::Custom))
556
558
  end
557
559
 
558
560
  def test_should_not_be_extended_by_the_integration_if_nil
559
- machine = StateMachine::Machine.new(Class.new, :integration => nil)
560
- assert !(class << machine; ancestors; end).include?(StateMachine::Integrations::Custom)
561
+ machine = StateMachine::Machine.new(@klass, :integration => nil)
562
+ assert(!(class << machine; ancestors; end).include?(StateMachine::Integrations::Custom))
561
563
  end
562
564
 
563
565
  def test_should_not_be_extended_by_the_integration_if_false
564
- machine = StateMachine::Machine.new(Class.new, :integration => false)
565
- assert !(class << machine; ancestors; end).include?(StateMachine::Integrations::Custom)
566
+ machine = StateMachine::Machine.new(@klass, :integration => false)
567
+ assert(!(class << machine; ancestors; end).include?(StateMachine::Integrations::Custom))
566
568
  end
567
569
 
568
570
  def teardown
571
+ self.class.send(:remove_const, 'Vehicle')
569
572
  StateMachine::Integrations.send(:remove_const, 'Custom')
570
573
  end
571
574
  end
@@ -653,11 +656,11 @@ class MachineWithActionUndefinedTest < Test::Unit::TestCase
653
656
  end
654
657
 
655
658
  def test_should_define_an_event_transition_attribute_reader
656
- assert @object.respond_to?(:state_event_transition)
659
+ assert @object.respond_to?(:state_event_transition, true)
657
660
  end
658
661
 
659
662
  def test_should_define_an_event_transition_attribute_writer
660
- assert @object.respond_to?(:state_event_transition=)
663
+ assert @object.respond_to?(:state_event_transition=, true)
661
664
  end
662
665
 
663
666
  def test_should_not_define_action
@@ -689,11 +692,11 @@ class MachineWithActionDefinedInClassTest < Test::Unit::TestCase
689
692
  end
690
693
 
691
694
  def test_should_define_an_event_transition_attribute_reader
692
- assert @object.respond_to?(:state_event_transition)
695
+ assert @object.respond_to?(:state_event_transition, true)
693
696
  end
694
697
 
695
698
  def test_should_define_an_event_transition_attribute_writer
696
- assert @object.respond_to?(:state_event_transition=)
699
+ assert @object.respond_to?(:state_event_transition=, true)
697
700
  end
698
701
 
699
702
  def test_should_not_define_action
@@ -729,11 +732,11 @@ class MachineWithActionDefinedInIncludedModuleTest < Test::Unit::TestCase
729
732
  end
730
733
 
731
734
  def test_should_define_an_event_transition_attribute_reader
732
- assert @object.respond_to?(:state_event_transition)
735
+ assert @object.respond_to?(:state_event_transition, true)
733
736
  end
734
737
 
735
738
  def test_should_define_an_event_transition_attribute_writer
736
- assert @object.respond_to?(:state_event_transition=)
739
+ assert @object.respond_to?(:state_event_transition=, true)
737
740
  end
738
741
 
739
742
  def test_should_define_action
@@ -770,11 +773,11 @@ class MachineWithActionDefinedInSuperclassTest < Test::Unit::TestCase
770
773
  end
771
774
 
772
775
  def test_should_define_an_event_transition_attribute_reader
773
- assert @object.respond_to?(:state_event_transition)
776
+ assert @object.respond_to?(:state_event_transition, true)
774
777
  end
775
778
 
776
779
  def test_should_define_an_event_transition_attribute_writer
777
- assert @object.respond_to?(:state_event_transition=)
780
+ assert @object.respond_to?(:state_event_transition=, true)
778
781
  end
779
782
 
780
783
  def test_should_define_action
@@ -812,11 +815,11 @@ class MachineWithPrivateActionTest < Test::Unit::TestCase
812
815
  end
813
816
 
814
817
  def test_should_define_an_event_transition_attribute_reader
815
- assert @object.respond_to?(:state_event_transition)
818
+ assert @object.respond_to?(:state_event_transition, true)
816
819
  end
817
820
 
818
821
  def test_should_define_an_event_transition_attribute_writer
819
- assert @object.respond_to?(:state_event_transition=)
822
+ assert @object.respond_to?(:state_event_transition=, true)
820
823
  end
821
824
 
822
825
  def test_should_define_action
@@ -875,17 +878,28 @@ class MachineWithCustomPluralTest < Test::Unit::TestCase
875
878
  end
876
879
 
877
880
  StateMachine::Integrations.const_set('Custom', @integration)
878
- @machine = StateMachine::Machine.new(Class.new, :integration => :custom, :plural => 'staties')
879
881
  end
880
882
 
881
883
  def test_should_define_a_singular_and_plural_with_scope
884
+ StateMachine::Machine.new(Class.new, :integration => :custom, :plural => 'staties')
882
885
  assert_equal %w(with_state with_staties), @integration.with_scopes
883
886
  end
884
887
 
885
888
  def test_should_define_a_singular_and_plural_without_scope
889
+ StateMachine::Machine.new(Class.new, :integration => :custom, :plural => 'staties')
886
890
  assert_equal %w(without_state without_staties), @integration.without_scopes
887
891
  end
888
892
 
893
+ def test_should_define_single_with_scope_if_singular_same_as_plural
894
+ StateMachine::Machine.new(Class.new, :integration => :custom, :plural => 'state')
895
+ assert_equal %w(with_state), @integration.with_scopes
896
+ end
897
+
898
+ def test_should_define_single_without_scope_if_singular_same_as_plural
899
+ StateMachine::Machine.new(Class.new, :integration => :custom, :plural => 'state')
900
+ assert_equal %w(without_state), @integration.without_scopes
901
+ end
902
+
889
903
  def teardown
890
904
  StateMachine::Integrations.send(:remove_const, 'Custom')
891
905
  end
@@ -1561,7 +1575,7 @@ class MachineWithConflictingHelpersBeforeDefinitionTest < Test::Unit::TestCase
1561
1575
  assert_equal :human_state_event_name, @klass.human_state_event_name
1562
1576
  end
1563
1577
 
1564
- def test_should_not_redefine_attribute_writer
1578
+ def test_should_not_redefine_attribute_reader
1565
1579
  assert_equal 'parked', @object.state
1566
1580
  end
1567
1581
 
@@ -1609,8 +1623,8 @@ class MachineWithConflictingHelpersBeforeDefinitionTest < Test::Unit::TestCase
1609
1623
  'Instance method "state_name"',
1610
1624
  'Instance method "human_state_name"',
1611
1625
  'Class method "with_state"',
1612
- 'Class method "without_state"',
1613
1626
  'Class method "with_states"',
1627
+ 'Class method "without_state"',
1614
1628
  'Class method "without_states"'
1615
1629
  ].map {|method| "#{method} is already defined in #{@superclass.to_s}, use generic helper instead or set StateMachine::Machine.ignore_method_conflicts = true.\n"}.join
1616
1630
 
@@ -1734,7 +1748,7 @@ class MachineWithConflictingHelpersAfterDefinitionTest < Test::Unit::TestCase
1734
1748
  assert_equal :human_state_event_name, @klass.human_state_event_name
1735
1749
  end
1736
1750
 
1737
- def test_should_not_redefine_attribute_writer
1751
+ def test_should_not_redefine_attribute_reader
1738
1752
  assert_equal 'parked', @object.state
1739
1753
  end
1740
1754
 
@@ -1975,8 +1989,9 @@ end
1975
1989
  class MachineWithCustomInitializeTest < Test::Unit::TestCase
1976
1990
  def setup
1977
1991
  @klass = Class.new do
1978
- def initialize
1979
- initialize_state_machines
1992
+ def initialize(state = nil, options = {})
1993
+ @state = state
1994
+ initialize_state_machines(options)
1980
1995
  end
1981
1996
  end
1982
1997
  @machine = StateMachine::Machine.new(@klass, :initial => :parked)
@@ -1986,6 +2001,12 @@ class MachineWithCustomInitializeTest < Test::Unit::TestCase
1986
2001
  def test_should_initialize_state
1987
2002
  assert_equal 'parked', @object.state
1988
2003
  end
2004
+
2005
+ def test_should_allow_custom_options
2006
+ @machine.state :idling
2007
+ @object = @klass.new('idling', :static => :force)
2008
+ assert_equal 'parked', @object.state
2009
+ end
1989
2010
  end
1990
2011
 
1991
2012
  class MachinePersistenceTest < Test::Unit::TestCase
@@ -2389,7 +2410,7 @@ class MachineWithEventMatchersTest < Test::Unit::TestCase
2389
2410
  end
2390
2411
 
2391
2412
  def test_should_track_referenced_events
2392
- event = @machine.event(StateMachine::BlacklistMatcher.new([:park]))
2413
+ @machine.event(StateMachine::BlacklistMatcher.new([:park]))
2393
2414
  assert_equal [:park], @machine.events.map {|event| event.name}
2394
2415
  end
2395
2416
 
@@ -2484,11 +2505,6 @@ class MachineWithTransitionsTest < Test::Unit::TestCase
2484
2505
  assert_equal 'Must specify :on event', exception.message
2485
2506
  end
2486
2507
 
2487
- def test_should_not_allow_except_to_option
2488
- exception = assert_raise(ArgumentError) {@machine.transition(:except_to => :parked, :on => :ignite)}
2489
- assert_equal 'Invalid key(s): except_to', exception.message
2490
- end
2491
-
2492
2508
  def test_should_not_allow_except_on_option
2493
2509
  exception = assert_raise(ArgumentError) {@machine.transition(:except_on => :ignite, :on => :ignite)}
2494
2510
  assert_equal 'Invalid key(s): except_on', exception.message
@@ -2506,6 +2522,10 @@ class MachineWithTransitionsTest < Test::Unit::TestCase
2506
2522
  assert_nothing_raised {@machine.transition(:except_from => :idling, :on => :ignite)}
2507
2523
  end
2508
2524
 
2525
+ def test_should_allow_except_to_option
2526
+ assert_nothing_raised {@machine.transition(:except_to => :parked, :on => :ignite)}
2527
+ end
2528
+
2509
2529
  def test_should_allow_implicit_options
2510
2530
  branch = @machine.transition(:first_gear => :second_gear, :on => :shift_up)
2511
2531
  assert_instance_of StateMachine::Branch, branch
@@ -2551,6 +2571,13 @@ class MachineWithTransitionsTest < Test::Unit::TestCase
2551
2571
  assert_equal 2, branches.length
2552
2572
  assert_equal [:ignite, :shift_up], @machine.events.map {|event| event.name}
2553
2573
  end
2574
+
2575
+ def test_should_not_modify_options
2576
+ options = {:parked => :idling, :on => :ignite}
2577
+ @machine.transition(options)
2578
+
2579
+ assert_equal options, {:parked => :idling, :on => :ignite}
2580
+ end
2554
2581
  end
2555
2582
 
2556
2583
  class MachineWithTransitionCallbacksTest < Test::Unit::TestCase
@@ -3157,7 +3184,7 @@ class MachineFinderWithExistingMachineOnSuperclassTest < Test::Unit::TestCase
3157
3184
  end
3158
3185
 
3159
3186
  def test_should_use_the_same_integration
3160
- assert (class << @machine; ancestors; end).include?(StateMachine::Integrations::Custom)
3187
+ assert((class << @machine; ancestors; end).include?(StateMachine::Integrations::Custom))
3161
3188
  end
3162
3189
 
3163
3190
  def teardown
@@ -3188,7 +3215,7 @@ begin
3188
3215
  class MachineDrawingTest < Test::Unit::TestCase
3189
3216
  def setup
3190
3217
  @klass = Class.new do
3191
- def self.name; 'Vehicle'; end
3218
+ def self.name; @name ||= "Vehicle_#{rand(1000000)}"; end
3192
3219
  end
3193
3220
  @machine = StateMachine::Machine.new(@klass, :initial => :parked)
3194
3221
  @machine.event :ignite do
@@ -3201,23 +3228,27 @@ begin
3201
3228
  end
3202
3229
 
3203
3230
  def test_should_save_file_with_class_name_by_default
3204
- graph = @machine.draw
3205
- assert File.exists?('./Vehicle_state.png')
3231
+ @machine.draw
3232
+ assert File.exists?("./#{@klass.name}_state.png")
3206
3233
  end
3207
3234
 
3208
3235
  def test_should_allow_base_name_to_be_customized
3209
- graph = @machine.draw(:name => 'machine')
3210
- assert File.exists?('./machine.png')
3236
+ name = "machine_#{rand(1000000)}"
3237
+ @machine.draw(:name => name)
3238
+ @path = "./#{name}.png"
3239
+ assert File.exists?(@path)
3211
3240
  end
3212
3241
 
3213
3242
  def test_should_allow_format_to_be_customized
3214
- graph = @machine.draw(:format => 'jpg')
3215
- assert File.exists?('./Vehicle_state.jpg')
3243
+ @machine.draw(:format => 'jpg')
3244
+ @path = "./#{@klass.name}_state.jpg"
3245
+ assert File.exists?(@path)
3216
3246
  end
3217
3247
 
3218
3248
  def test_should_allow_path_to_be_customized
3219
- graph = @machine.draw(:path => "#{File.dirname(__FILE__)}/")
3220
- assert File.exists?("#{File.dirname(__FILE__)}/Vehicle_state.png")
3249
+ @machine.draw(:path => "#{File.dirname(__FILE__)}/")
3250
+ @path = "#{File.dirname(__FILE__)}/#{@klass.name}_state.png"
3251
+ assert File.exists?(@path)
3221
3252
  end
3222
3253
 
3223
3254
  def test_should_allow_orientation_to_be_landscape
@@ -3230,15 +3261,30 @@ begin
3230
3261
  assert_equal 'TB', graph['rankdir'].to_s.gsub('"', '')
3231
3262
  end
3232
3263
 
3264
+ if Constants::RGV_VERSION != '0.9.0'
3265
+ def test_should_allow_human_names_to_be_displayed
3266
+ @machine.event :ignite, :human_name => 'Ignite'
3267
+ @machine.state :parked, :human_name => 'Parked'
3268
+ @machine.state :idling, :human_name => 'Idling'
3269
+ graph = @machine.draw(:human_names => true)
3270
+
3271
+ parked_node = graph.get_node('parked')
3272
+ assert_equal 'Parked', parked_node['label'].to_s.gsub('"', '')
3273
+
3274
+ idling_node = graph.get_node('idling')
3275
+ assert_equal 'Idling', idling_node['label'].to_s.gsub('"', '')
3276
+ end
3277
+ end
3278
+
3233
3279
  def teardown
3234
- FileUtils.rm Dir["{.,#{File.dirname(__FILE__)}}/*.{png,jpg}"]
3280
+ FileUtils.rm Dir[@path || "./#{@klass.name}_state.png"]
3235
3281
  end
3236
3282
  end
3237
3283
 
3238
3284
  class MachineDrawingWithIntegerStatesTest < Test::Unit::TestCase
3239
3285
  def setup
3240
3286
  @klass = Class.new do
3241
- def self.name; 'Vehicle'; end
3287
+ def self.name; @name ||= "Vehicle_#{rand(1000000)}"; end
3242
3288
  end
3243
3289
  @machine = StateMachine::Machine.new(@klass, :state_id, :initial => :parked)
3244
3290
  @machine.event :ignite do
@@ -3258,16 +3304,18 @@ begin
3258
3304
  end
3259
3305
 
3260
3306
  def test_should_draw_machine
3261
- assert File.exist?('./Vehicle_state_id.png')
3262
- ensure
3263
- FileUtils.rm('./Vehicle_state_id.png')
3307
+ assert File.exist?("./#{@klass.name}_state_id.png")
3308
+ end
3309
+
3310
+ def teardown
3311
+ FileUtils.rm Dir["./#{@klass.name}_state_id.png"]
3264
3312
  end
3265
3313
  end
3266
3314
 
3267
3315
  class MachineDrawingWithNilStatesTest < Test::Unit::TestCase
3268
3316
  def setup
3269
3317
  @klass = Class.new do
3270
- def self.name; 'Vehicle'; end
3318
+ def self.name; @name ||= "Vehicle_#{rand(1000000)}"; end
3271
3319
  end
3272
3320
  @machine = StateMachine::Machine.new(@klass, :initial => :parked)
3273
3321
  @machine.event :ignite do
@@ -3286,16 +3334,18 @@ begin
3286
3334
  end
3287
3335
 
3288
3336
  def test_should_draw_machine
3289
- assert File.exist?('./Vehicle_state.png')
3290
- ensure
3291
- FileUtils.rm('./Vehicle_state.png')
3337
+ assert File.exist?("./#{@klass.name}_state.png")
3338
+ end
3339
+
3340
+ def teardown
3341
+ FileUtils.rm Dir["./#{@klass.name}_state.png"]
3292
3342
  end
3293
3343
  end
3294
3344
 
3295
3345
  class MachineDrawingWithDynamicStatesTest < Test::Unit::TestCase
3296
3346
  def setup
3297
3347
  @klass = Class.new do
3298
- def self.name; 'Vehicle'; end
3348
+ def self.name; @name ||= "Vehicle_#{rand(1000000)}"; end
3299
3349
  end
3300
3350
  @machine = StateMachine::Machine.new(@klass, :initial => :parked)
3301
3351
  @machine.event :activate do
@@ -3314,16 +3364,18 @@ begin
3314
3364
  end
3315
3365
 
3316
3366
  def test_should_draw_machine
3317
- assert File.exist?('./Vehicle_state.png')
3318
- ensure
3319
- FileUtils.rm('./Vehicle_state.png')
3367
+ assert File.exist?("./#{@klass.name}_state.png")
3368
+ end
3369
+
3370
+ def teardown
3371
+ FileUtils.rm Dir["./#{@klass.name}_state.png"]
3320
3372
  end
3321
3373
  end
3322
3374
 
3323
3375
  class MachineClassDrawingTest < Test::Unit::TestCase
3324
3376
  def setup
3325
3377
  @klass = Class.new do
3326
- def self.name; 'Vehicle'; end
3378
+ def self.name; @name ||= "Vehicle_#{rand(1000000)}"; end
3327
3379
  end
3328
3380
  @machine = StateMachine::Machine.new(@klass)
3329
3381
  @machine.event :ignite do
@@ -3339,17 +3391,17 @@ begin
3339
3391
  def test_should_load_files
3340
3392
  StateMachine::Machine.draw('Switch', :file => File.expand_path("#{File.dirname(__FILE__)}/../files/switch.rb"))
3341
3393
  assert defined?(::Switch)
3342
- ensure
3343
- FileUtils.rm('./Switch_state.png')
3344
3394
  end
3345
3395
 
3346
3396
  def test_should_allow_path_and_format_to_be_customized
3347
3397
  StateMachine::Machine.draw('Switch', :file => File.expand_path("#{File.dirname(__FILE__)}/../files/switch.rb"), :path => "#{File.dirname(__FILE__)}/", :format => 'jpg')
3348
- assert File.exist?("#{File.dirname(__FILE__)}/Switch_state.jpg")
3349
- ensure
3350
- FileUtils.rm("#{File.dirname(__FILE__)}/Switch_state.jpg")
3398
+ assert File.exist?("#{File.dirname(__FILE__)}/#{Switch.name}_state.jpg")
3399
+ end
3400
+
3401
+ def teardown
3402
+ FileUtils.rm Dir["{.,#{File.dirname(__FILE__)}}/#{Switch.name}_state.{jpg,png}"]
3351
3403
  end
3352
3404
  end
3353
3405
  rescue LoadError
3354
- $stderr.puts 'Skipping GraphViz StateMachine::Machine tests. `gem install ruby-graphviz` >= v0.9.0 and try again.'
3406
+ $stderr.puts 'Skipping GraphViz StateMachine::Machine tests. `gem install ruby-graphviz` >= v0.9.17 and try again.'
3355
3407
  end unless ENV['TRAVIS']