telvue_state_machine 1.2.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 (307) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.travis.yml +72 -0
  4. data/.yardopts +5 -0
  5. data/Appraisals +491 -0
  6. data/CHANGELOG.md +502 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +20 -0
  9. data/README.md +1263 -0
  10. data/Rakefile +41 -0
  11. data/examples/AutoShop_state.png +0 -0
  12. data/examples/Car_state.png +0 -0
  13. data/examples/Gemfile +5 -0
  14. data/examples/Gemfile.lock +14 -0
  15. data/examples/TrafficLight_state.png +0 -0
  16. data/examples/Vehicle_state.png +0 -0
  17. data/examples/auto_shop.rb +13 -0
  18. data/examples/car.rb +21 -0
  19. data/examples/doc/AutoShop.html +2856 -0
  20. data/examples/doc/AutoShop_state.png +0 -0
  21. data/examples/doc/Car.html +919 -0
  22. data/examples/doc/Car_state.png +0 -0
  23. data/examples/doc/TrafficLight.html +2230 -0
  24. data/examples/doc/TrafficLight_state.png +0 -0
  25. data/examples/doc/Vehicle.html +7921 -0
  26. data/examples/doc/Vehicle_state.png +0 -0
  27. data/examples/doc/_index.html +136 -0
  28. data/examples/doc/class_list.html +47 -0
  29. data/examples/doc/css/common.css +1 -0
  30. data/examples/doc/css/full_list.css +55 -0
  31. data/examples/doc/css/style.css +322 -0
  32. data/examples/doc/file_list.html +46 -0
  33. data/examples/doc/frames.html +13 -0
  34. data/examples/doc/index.html +136 -0
  35. data/examples/doc/js/app.js +205 -0
  36. data/examples/doc/js/full_list.js +173 -0
  37. data/examples/doc/js/jquery.js +16 -0
  38. data/examples/doc/method_list.html +734 -0
  39. data/examples/doc/top-level-namespace.html +105 -0
  40. data/examples/merb-rest/controller.rb +51 -0
  41. data/examples/merb-rest/model.rb +28 -0
  42. data/examples/merb-rest/view_edit.html.erb +24 -0
  43. data/examples/merb-rest/view_index.html.erb +23 -0
  44. data/examples/merb-rest/view_new.html.erb +13 -0
  45. data/examples/merb-rest/view_show.html.erb +17 -0
  46. data/examples/rails-rest/controller.rb +43 -0
  47. data/examples/rails-rest/migration.rb +7 -0
  48. data/examples/rails-rest/model.rb +23 -0
  49. data/examples/rails-rest/view__form.html.erb +34 -0
  50. data/examples/rails-rest/view_edit.html.erb +6 -0
  51. data/examples/rails-rest/view_index.html.erb +25 -0
  52. data/examples/rails-rest/view_new.html.erb +5 -0
  53. data/examples/rails-rest/view_show.html.erb +19 -0
  54. data/examples/traffic_light.rb +9 -0
  55. data/examples/vehicle.rb +33 -0
  56. data/gemfiles/active_model_3.0.0.gemfile +7 -0
  57. data/gemfiles/active_model_3.0.0.gemfile.lock +35 -0
  58. data/gemfiles/active_model_3.0.5.gemfile +7 -0
  59. data/gemfiles/active_model_3.0.5.gemfile.lock +35 -0
  60. data/gemfiles/active_model_3.1.1.gemfile +7 -0
  61. data/gemfiles/active_model_3.1.1.gemfile.lock +36 -0
  62. data/gemfiles/active_model_3.2.1.gemfile +7 -0
  63. data/gemfiles/active_model_3.2.12.gemfile +7 -0
  64. data/gemfiles/active_model_3.2.12.gemfile.lock +36 -0
  65. data/gemfiles/active_model_3.2.13.rc1.gemfile +7 -0
  66. data/gemfiles/active_model_3.2.13.rc1.gemfile.lock +36 -0
  67. data/gemfiles/active_model_4.0.0.gemfile +9 -0
  68. data/gemfiles/active_model_4.0.0.gemfile.lock +78 -0
  69. data/gemfiles/active_record_2.0.0.gemfile +9 -0
  70. data/gemfiles/active_record_2.0.0.gemfile.lock +39 -0
  71. data/gemfiles/active_record_2.0.5.gemfile +9 -0
  72. data/gemfiles/active_record_2.0.5.gemfile.lock +39 -0
  73. data/gemfiles/active_record_2.1.0.gemfile +9 -0
  74. data/gemfiles/active_record_2.1.0.gemfile.lock +39 -0
  75. data/gemfiles/active_record_2.1.2.gemfile +9 -0
  76. data/gemfiles/active_record_2.1.2.gemfile.lock +39 -0
  77. data/gemfiles/active_record_2.2.3.gemfile +9 -0
  78. data/gemfiles/active_record_2.2.3.gemfile.lock +39 -0
  79. data/gemfiles/active_record_2.3.12.gemfile +9 -0
  80. data/gemfiles/active_record_2.3.12.gemfile.lock +39 -0
  81. data/gemfiles/active_record_2.3.5.gemfile +9 -0
  82. data/gemfiles/active_record_2.3.5.gemfile.lock +39 -0
  83. data/gemfiles/active_record_3.0.0.gemfile +9 -0
  84. data/gemfiles/active_record_3.0.0.gemfile.lock +51 -0
  85. data/gemfiles/active_record_3.0.5.gemfile +9 -0
  86. data/gemfiles/active_record_3.0.5.gemfile.lock +50 -0
  87. data/gemfiles/active_record_3.1.1.gemfile +9 -0
  88. data/gemfiles/active_record_3.1.1.gemfile.lock +51 -0
  89. data/gemfiles/active_record_3.2.12.gemfile +9 -0
  90. data/gemfiles/active_record_3.2.12.gemfile.lock +51 -0
  91. data/gemfiles/active_record_3.2.13.rc1.gemfile +9 -0
  92. data/gemfiles/active_record_3.2.13.rc1.gemfile.lock +51 -0
  93. data/gemfiles/active_record_4.0.0.gemfile +11 -0
  94. data/gemfiles/active_record_4.0.0.gemfile.lock +83 -0
  95. data/gemfiles/data_mapper_0.10.2.gemfile +13 -0
  96. data/gemfiles/data_mapper_0.10.2.gemfile.lock +56 -0
  97. data/gemfiles/data_mapper_0.9.11.gemfile +13 -0
  98. data/gemfiles/data_mapper_0.9.11.gemfile.lock +71 -0
  99. data/gemfiles/data_mapper_0.9.4.gemfile +12 -0
  100. data/gemfiles/data_mapper_0.9.4.gemfile.lock +70 -0
  101. data/gemfiles/data_mapper_0.9.7.gemfile +13 -0
  102. data/gemfiles/data_mapper_0.9.7.gemfile.lock +67 -0
  103. data/gemfiles/data_mapper_1.0.0.gemfile +12 -0
  104. data/gemfiles/data_mapper_1.0.0.gemfile.lock +63 -0
  105. data/gemfiles/data_mapper_1.0.1.gemfile +12 -0
  106. data/gemfiles/data_mapper_1.0.1.gemfile.lock +63 -0
  107. data/gemfiles/data_mapper_1.0.2.gemfile +12 -0
  108. data/gemfiles/data_mapper_1.0.2.gemfile.lock +63 -0
  109. data/gemfiles/data_mapper_1.1.0.gemfile +12 -0
  110. data/gemfiles/data_mapper_1.1.0.gemfile.lock +61 -0
  111. data/gemfiles/data_mapper_1.2.0.gemfile +12 -0
  112. data/gemfiles/data_mapper_1.2.0.gemfile.lock +61 -0
  113. data/gemfiles/default.gemfile +7 -0
  114. data/gemfiles/default.gemfile.lock +27 -0
  115. data/gemfiles/graphviz_0.9.17.gemfile +7 -0
  116. data/gemfiles/graphviz_0.9.17.gemfile.lock +29 -0
  117. data/gemfiles/graphviz_0.9.21.gemfile +7 -0
  118. data/gemfiles/graphviz_0.9.21.gemfile.lock +29 -0
  119. data/gemfiles/graphviz_1.0.0.gemfile +7 -0
  120. data/gemfiles/graphviz_1.0.0.gemfile.lock +29 -0
  121. data/gemfiles/graphviz_1.0.3.gemfile +7 -0
  122. data/gemfiles/graphviz_1.0.3.gemfile.lock +29 -0
  123. data/gemfiles/graphviz_1.0.8.gemfile +7 -0
  124. data/gemfiles/graphviz_1.0.8.gemfile.lock +29 -0
  125. data/gemfiles/mongo_mapper_0.10.0.gemfile +8 -0
  126. data/gemfiles/mongo_mapper_0.10.0.gemfile.lock +47 -0
  127. data/gemfiles/mongo_mapper_0.11.2.gemfile +9 -0
  128. data/gemfiles/mongo_mapper_0.11.2.gemfile.lock +48 -0
  129. data/gemfiles/mongo_mapper_0.12.0.gemfile +9 -0
  130. data/gemfiles/mongo_mapper_0.12.0.gemfile.lock +48 -0
  131. data/gemfiles/mongo_mapper_0.5.5.gemfile +8 -0
  132. data/gemfiles/mongo_mapper_0.5.5.gemfile.lock +36 -0
  133. data/gemfiles/mongo_mapper_0.5.8.gemfile +8 -0
  134. data/gemfiles/mongo_mapper_0.5.8.gemfile.lock +36 -0
  135. data/gemfiles/mongo_mapper_0.6.0.gemfile +8 -0
  136. data/gemfiles/mongo_mapper_0.6.0.gemfile.lock +36 -0
  137. data/gemfiles/mongo_mapper_0.6.10.gemfile +8 -0
  138. data/gemfiles/mongo_mapper_0.6.10.gemfile.lock +36 -0
  139. data/gemfiles/mongo_mapper_0.7.0.gemfile +8 -0
  140. data/gemfiles/mongo_mapper_0.7.0.gemfile.lock +36 -0
  141. data/gemfiles/mongo_mapper_0.7.5.gemfile +8 -0
  142. data/gemfiles/mongo_mapper_0.7.5.gemfile.lock +39 -0
  143. data/gemfiles/mongo_mapper_0.8.0.gemfile +10 -0
  144. data/gemfiles/mongo_mapper_0.8.0.gemfile.lock +43 -0
  145. data/gemfiles/mongo_mapper_0.8.3.gemfile +10 -0
  146. data/gemfiles/mongo_mapper_0.8.3.gemfile.lock +43 -0
  147. data/gemfiles/mongo_mapper_0.8.4.gemfile +8 -0
  148. data/gemfiles/mongo_mapper_0.8.4.gemfile.lock +42 -0
  149. data/gemfiles/mongo_mapper_0.8.6.gemfile +8 -0
  150. data/gemfiles/mongo_mapper_0.8.6.gemfile.lock +42 -0
  151. data/gemfiles/mongo_mapper_0.9.0.gemfile +7 -0
  152. data/gemfiles/mongo_mapper_0.9.0.gemfile.lock +45 -0
  153. data/gemfiles/mongoid_2.0.0.gemfile +9 -0
  154. data/gemfiles/mongoid_2.0.0.gemfile.lock +49 -0
  155. data/gemfiles/mongoid_2.1.4.gemfile +9 -0
  156. data/gemfiles/mongoid_2.1.4.gemfile.lock +47 -0
  157. data/gemfiles/mongoid_2.2.4.gemfile +9 -0
  158. data/gemfiles/mongoid_2.2.4.gemfile.lock +47 -0
  159. data/gemfiles/mongoid_2.3.3.gemfile +9 -0
  160. data/gemfiles/mongoid_2.3.3.gemfile.lock +47 -0
  161. data/gemfiles/mongoid_2.4.0.gemfile +9 -0
  162. data/gemfiles/mongoid_2.4.0.gemfile.lock +47 -0
  163. data/gemfiles/mongoid_2.4.10.gemfile +9 -0
  164. data/gemfiles/mongoid_2.4.10.gemfile.lock +47 -0
  165. data/gemfiles/mongoid_2.5.2.gemfile +9 -0
  166. data/gemfiles/mongoid_2.5.2.gemfile.lock +47 -0
  167. data/gemfiles/mongoid_2.6.0.gemfile +9 -0
  168. data/gemfiles/mongoid_2.6.0.gemfile.lock +47 -0
  169. data/gemfiles/mongoid_3.0.0.gemfile +8 -0
  170. data/gemfiles/mongoid_3.0.0.gemfile.lock +45 -0
  171. data/gemfiles/mongoid_3.0.22.gemfile +8 -0
  172. data/gemfiles/mongoid_3.0.22.gemfile.lock +45 -0
  173. data/gemfiles/mongoid_3.1.0.gemfile +8 -0
  174. data/gemfiles/mongoid_3.1.0.gemfile.lock +45 -0
  175. data/gemfiles/sequel_2.11.0.gemfile +9 -0
  176. data/gemfiles/sequel_2.11.0.gemfile.lock +33 -0
  177. data/gemfiles/sequel_2.12.0.gemfile +9 -0
  178. data/gemfiles/sequel_2.12.0.gemfile.lock +33 -0
  179. data/gemfiles/sequel_2.8.0.gemfile +9 -0
  180. data/gemfiles/sequel_2.8.0.gemfile.lock +33 -0
  181. data/gemfiles/sequel_3.0.0.gemfile +9 -0
  182. data/gemfiles/sequel_3.0.0.gemfile.lock +33 -0
  183. data/gemfiles/sequel_3.10.0.gemfile +9 -0
  184. data/gemfiles/sequel_3.10.0.gemfile.lock +33 -0
  185. data/gemfiles/sequel_3.13.0.gemfile +9 -0
  186. data/gemfiles/sequel_3.13.0.gemfile.lock +33 -0
  187. data/gemfiles/sequel_3.14.0.gemfile +9 -0
  188. data/gemfiles/sequel_3.14.0.gemfile.lock +33 -0
  189. data/gemfiles/sequel_3.23.0.gemfile +9 -0
  190. data/gemfiles/sequel_3.23.0.gemfile.lock +33 -0
  191. data/gemfiles/sequel_3.24.0.gemfile +9 -0
  192. data/gemfiles/sequel_3.24.0.gemfile.lock +33 -0
  193. data/gemfiles/sequel_3.29.0.gemfile +9 -0
  194. data/gemfiles/sequel_3.29.0.gemfile.lock +33 -0
  195. data/gemfiles/sequel_3.34.0.gemfile +9 -0
  196. data/gemfiles/sequel_3.34.0.gemfile.lock +33 -0
  197. data/gemfiles/sequel_3.35.0.gemfile +9 -0
  198. data/gemfiles/sequel_3.35.0.gemfile.lock +33 -0
  199. data/gemfiles/sequel_3.4.0.gemfile +9 -0
  200. data/gemfiles/sequel_3.4.0.gemfile.lock +33 -0
  201. data/gemfiles/sequel_3.44.0.gemfile +9 -0
  202. data/gemfiles/sequel_3.44.0.gemfile.lock +33 -0
  203. data/init.rb +1 -0
  204. data/lib/state_machine.rb +8 -0
  205. data/lib/state_machine/assertions.rb +36 -0
  206. data/lib/state_machine/branch.rb +225 -0
  207. data/lib/state_machine/callback.rb +236 -0
  208. data/lib/state_machine/core.rb +12 -0
  209. data/lib/state_machine/core_ext.rb +2 -0
  210. data/lib/state_machine/core_ext/class/state_machine.rb +5 -0
  211. data/lib/state_machine/error.rb +13 -0
  212. data/lib/state_machine/eval_helpers.rb +87 -0
  213. data/lib/state_machine/event.rb +257 -0
  214. data/lib/state_machine/event_collection.rb +141 -0
  215. data/lib/state_machine/extensions.rb +149 -0
  216. data/lib/state_machine/graph.rb +92 -0
  217. data/lib/state_machine/helper_module.rb +17 -0
  218. data/lib/state_machine/initializers.rb +4 -0
  219. data/lib/state_machine/initializers/merb.rb +1 -0
  220. data/lib/state_machine/initializers/rails.rb +25 -0
  221. data/lib/state_machine/integrations.rb +121 -0
  222. data/lib/state_machine/integrations/active_model.rb +585 -0
  223. data/lib/state_machine/integrations/active_model/locale.rb +11 -0
  224. data/lib/state_machine/integrations/active_model/observer.rb +33 -0
  225. data/lib/state_machine/integrations/active_model/observer_update.rb +42 -0
  226. data/lib/state_machine/integrations/active_model/versions.rb +31 -0
  227. data/lib/state_machine/integrations/active_record.rb +552 -0
  228. data/lib/state_machine/integrations/active_record/locale.rb +20 -0
  229. data/lib/state_machine/integrations/active_record/versions.rb +123 -0
  230. data/lib/state_machine/integrations/base.rb +100 -0
  231. data/lib/state_machine/integrations/data_mapper.rb +511 -0
  232. data/lib/state_machine/integrations/data_mapper/observer.rb +210 -0
  233. data/lib/state_machine/integrations/data_mapper/versions.rb +85 -0
  234. data/lib/state_machine/integrations/mongo_mapper.rb +389 -0
  235. data/lib/state_machine/integrations/mongo_mapper/locale.rb +4 -0
  236. data/lib/state_machine/integrations/mongo_mapper/versions.rb +89 -0
  237. data/lib/state_machine/integrations/mongoid.rb +465 -0
  238. data/lib/state_machine/integrations/mongoid/locale.rb +4 -0
  239. data/lib/state_machine/integrations/mongoid/versions.rb +81 -0
  240. data/lib/state_machine/integrations/sequel.rb +486 -0
  241. data/lib/state_machine/integrations/sequel/versions.rb +95 -0
  242. data/lib/state_machine/machine.rb +2292 -0
  243. data/lib/state_machine/machine_collection.rb +86 -0
  244. data/lib/state_machine/macro_methods.rb +522 -0
  245. data/lib/state_machine/matcher.rb +123 -0
  246. data/lib/state_machine/matcher_helpers.rb +54 -0
  247. data/lib/state_machine/node_collection.rb +222 -0
  248. data/lib/state_machine/path.rb +120 -0
  249. data/lib/state_machine/path_collection.rb +90 -0
  250. data/lib/state_machine/state.rb +297 -0
  251. data/lib/state_machine/state_collection.rb +112 -0
  252. data/lib/state_machine/state_context.rb +138 -0
  253. data/lib/state_machine/transition.rb +470 -0
  254. data/lib/state_machine/transition_collection.rb +245 -0
  255. data/lib/state_machine/version.rb +3 -0
  256. data/lib/state_machine/yard.rb +8 -0
  257. data/lib/state_machine/yard/handlers.rb +12 -0
  258. data/lib/state_machine/yard/handlers/base.rb +32 -0
  259. data/lib/state_machine/yard/handlers/event.rb +25 -0
  260. data/lib/state_machine/yard/handlers/machine.rb +344 -0
  261. data/lib/state_machine/yard/handlers/state.rb +25 -0
  262. data/lib/state_machine/yard/handlers/transition.rb +47 -0
  263. data/lib/state_machine/yard/templates.rb +3 -0
  264. data/lib/state_machine/yard/templates/default/class/html/setup.rb +30 -0
  265. data/lib/state_machine/yard/templates/default/class/html/state_machines.erb +12 -0
  266. data/lib/tasks/state_machine.rake +1 -0
  267. data/lib/tasks/state_machine.rb +30 -0
  268. data/lib/yard-state_machine.rb +2 -0
  269. data/state_machine.gemspec +22 -0
  270. data/test/files/en.yml +17 -0
  271. data/test/files/switch.rb +15 -0
  272. data/test/functional/state_machine_test.rb +1066 -0
  273. data/test/test_helper.rb +7 -0
  274. data/test/unit/assertions_test.rb +40 -0
  275. data/test/unit/branch_test.rb +969 -0
  276. data/test/unit/callback_test.rb +704 -0
  277. data/test/unit/error_test.rb +43 -0
  278. data/test/unit/eval_helpers_test.rb +270 -0
  279. data/test/unit/event_collection_test.rb +398 -0
  280. data/test/unit/event_test.rb +1196 -0
  281. data/test/unit/graph_test.rb +98 -0
  282. data/test/unit/helper_module_test.rb +17 -0
  283. data/test/unit/integrations/active_model_test.rb +1245 -0
  284. data/test/unit/integrations/active_record_test.rb +2551 -0
  285. data/test/unit/integrations/base_test.rb +104 -0
  286. data/test/unit/integrations/data_mapper_test.rb +2194 -0
  287. data/test/unit/integrations/mongo_mapper_test.rb +2026 -0
  288. data/test/unit/integrations/mongoid_test.rb +2309 -0
  289. data/test/unit/integrations/sequel_test.rb +1896 -0
  290. data/test/unit/integrations_test.rb +83 -0
  291. data/test/unit/invalid_event_test.rb +20 -0
  292. data/test/unit/invalid_parallel_transition_test.rb +18 -0
  293. data/test/unit/invalid_transition_test.rb +115 -0
  294. data/test/unit/machine_collection_test.rb +603 -0
  295. data/test/unit/machine_test.rb +3431 -0
  296. data/test/unit/matcher_helpers_test.rb +37 -0
  297. data/test/unit/matcher_test.rb +155 -0
  298. data/test/unit/node_collection_test.rb +362 -0
  299. data/test/unit/path_collection_test.rb +266 -0
  300. data/test/unit/path_test.rb +485 -0
  301. data/test/unit/state_collection_test.rb +352 -0
  302. data/test/unit/state_context_test.rb +441 -0
  303. data/test/unit/state_machine_test.rb +31 -0
  304. data/test/unit/state_test.rb +1101 -0
  305. data/test/unit/transition_collection_test.rb +2168 -0
  306. data/test/unit/transition_test.rb +1558 -0
  307. metadata +435 -0
@@ -0,0 +1,266 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class PathCollectionByDefaultTest < Test::Unit::TestCase
4
+ def setup
5
+ @klass = Class.new
6
+ @machine = StateMachine::Machine.new(@klass)
7
+ @machine.state :parked
8
+
9
+ @object = @klass.new
10
+ @object.state = 'parked'
11
+
12
+ @paths = StateMachine::PathCollection.new(@object, @machine)
13
+ end
14
+
15
+ def test_should_have_an_object
16
+ assert_equal @object, @paths.object
17
+ end
18
+
19
+ def test_should_have_a_machine
20
+ assert_equal @machine, @paths.machine
21
+ end
22
+
23
+ def test_should_have_a_from_name
24
+ assert_equal :parked, @paths.from_name
25
+ end
26
+
27
+ def test_should_not_have_a_to_name
28
+ assert_nil @paths.to_name
29
+ end
30
+
31
+ def test_should_have_no_from_states
32
+ assert_equal [], @paths.from_states
33
+ end
34
+
35
+ def test_should_have_no_to_states
36
+ assert_equal [], @paths.to_states
37
+ end
38
+
39
+ def test_should_have_no_events
40
+ assert_equal [], @paths.events
41
+ end
42
+
43
+ def test_should_have_no_paths
44
+ assert @paths.empty?
45
+ end
46
+ end
47
+
48
+ class PathCollectionTest < Test::Unit::TestCase
49
+ def setup
50
+ @klass = Class.new
51
+ @machine = StateMachine::Machine.new(@klass)
52
+ @object = @klass.new
53
+ end
54
+
55
+ def test_should_raise_exception_if_invalid_option_specified
56
+ exception = assert_raise(ArgumentError) {StateMachine::PathCollection.new(@object, @machine, :invalid => true)}
57
+ assert_equal 'Invalid key(s): invalid', exception.message
58
+ end
59
+
60
+ def test_should_raise_exception_if_invalid_from_state_specified
61
+ exception = assert_raise(IndexError) {StateMachine::PathCollection.new(@object, @machine, :from => :invalid)}
62
+ assert_equal ':invalid is an invalid name', exception.message
63
+ end
64
+
65
+ def test_should_raise_exception_if_invalid_to_state_specified
66
+ exception = assert_raise(IndexError) {StateMachine::PathCollection.new(@object, @machine, :to => :invalid)}
67
+ assert_equal ':invalid is an invalid name', exception.message
68
+ end
69
+ end
70
+
71
+ class PathCollectionWithPathsTest < Test::Unit::TestCase
72
+ def setup
73
+ @klass = Class.new
74
+ @machine = StateMachine::Machine.new(@klass)
75
+ @machine.state :parked, :idling, :first_gear
76
+ @machine.event :ignite do
77
+ transition :parked => :idling
78
+ end
79
+ @machine.event :shift_up do
80
+ transition :idling => :first_gear
81
+ end
82
+
83
+ @object = @klass.new
84
+ @object.state = 'parked'
85
+
86
+ @paths = StateMachine::PathCollection.new(@object, @machine)
87
+ end
88
+
89
+ def test_should_enumerate_paths
90
+ assert_equal [[
91
+ StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
92
+ StateMachine::Transition.new(@object, @machine, :shift_up, :idling, :first_gear)
93
+ ]], @paths
94
+ end
95
+
96
+ def test_should_have_a_from_name
97
+ assert_equal :parked, @paths.from_name
98
+ end
99
+
100
+ def test_should_not_have_a_to_name
101
+ assert_nil @paths.to_name
102
+ end
103
+
104
+ def test_should_have_from_states
105
+ assert_equal [:parked, :idling], @paths.from_states
106
+ end
107
+
108
+ def test_should_have_to_states
109
+ assert_equal [:idling, :first_gear], @paths.to_states
110
+ end
111
+
112
+ def test_should_have_no_events
113
+ assert_equal [:ignite, :shift_up], @paths.events
114
+ end
115
+ end
116
+
117
+ class PathWithGuardedPathsTest < Test::Unit::TestCase
118
+ def setup
119
+ @klass = Class.new
120
+ @machine = StateMachine::Machine.new(@klass)
121
+ @machine.state :parked, :idling, :first_gear
122
+ @machine.event :ignite do
123
+ transition :parked => :idling, :if => lambda {false}
124
+ end
125
+
126
+ @object = @klass.new
127
+ @object.state = 'parked'
128
+ end
129
+
130
+ def test_should_not_enumerate_paths_if_guard_enabled
131
+ assert_equal [], StateMachine::PathCollection.new(@object, @machine)
132
+ end
133
+
134
+ def test_should_enumerate_paths_if_guard_disabled
135
+ paths = StateMachine::PathCollection.new(@object, @machine, :guard => false)
136
+ assert_equal [[
137
+ StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
138
+ ]], paths
139
+ end
140
+ end
141
+
142
+ class PathCollectionWithDuplicateNodesTest < Test::Unit::TestCase
143
+ def setup
144
+ @klass = Class.new
145
+ @machine = StateMachine::Machine.new(@klass)
146
+ @machine.state :parked, :idling
147
+ @machine.event :shift_up do
148
+ transition :parked => :idling, :idling => :first_gear
149
+ end
150
+ @machine.event :park do
151
+ transition :first_gear => :idling
152
+ end
153
+ @object = @klass.new
154
+ @object.state = 'parked'
155
+
156
+ @paths = StateMachine::PathCollection.new(@object, @machine)
157
+ end
158
+
159
+ def test_should_not_include_duplicates_in_from_states
160
+ assert_equal [:parked, :idling, :first_gear], @paths.from_states
161
+ end
162
+
163
+ def test_should_not_include_duplicates_in_to_states
164
+ assert_equal [:idling, :first_gear], @paths.to_states
165
+ end
166
+
167
+ def test_should_not_include_duplicates_in_events
168
+ assert_equal [:shift_up, :park], @paths.events
169
+ end
170
+ end
171
+
172
+ class PathCollectionWithFromStateTest < Test::Unit::TestCase
173
+ def setup
174
+ @klass = Class.new
175
+ @machine = StateMachine::Machine.new(@klass)
176
+ @machine.state :parked, :idling, :first_gear
177
+ @machine.event :park do
178
+ transition :idling => :parked
179
+ end
180
+
181
+ @object = @klass.new
182
+ @object.state = 'parked'
183
+
184
+ @paths = StateMachine::PathCollection.new(@object, @machine, :from => :idling)
185
+ end
186
+
187
+ def test_should_generate_paths_from_custom_from_state
188
+ assert_equal [[
189
+ StateMachine::Transition.new(@object, @machine, :park, :idling, :parked)
190
+ ]], @paths
191
+ end
192
+
193
+ def test_should_have_a_from_name
194
+ assert_equal :idling, @paths.from_name
195
+ end
196
+ end
197
+
198
+ class PathCollectionWithToStateTest < Test::Unit::TestCase
199
+ def setup
200
+ @klass = Class.new
201
+ @machine = StateMachine::Machine.new(@klass)
202
+ @machine.state :parked, :idling
203
+ @machine.event :ignite do
204
+ transition :parked => :idling
205
+ end
206
+ @machine.event :shift_up do
207
+ transition :parked => :idling, :idling => :first_gear
208
+ end
209
+ @machine.event :shift_down do
210
+ transition :first_gear => :idling
211
+ end
212
+ @object = @klass.new
213
+ @object.state = 'parked'
214
+
215
+ @paths = StateMachine::PathCollection.new(@object, @machine, :to => :idling)
216
+ end
217
+
218
+ def test_should_stop_paths_once_target_state_reached
219
+ assert_equal [
220
+ [StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)],
221
+ [StateMachine::Transition.new(@object, @machine, :shift_up, :parked, :idling)]
222
+ ], @paths
223
+ end
224
+ end
225
+
226
+ class PathCollectionWithDeepPathsTest < Test::Unit::TestCase
227
+ def setup
228
+ @klass = Class.new
229
+ @machine = StateMachine::Machine.new(@klass)
230
+ @machine.state :parked, :idling
231
+ @machine.event :ignite do
232
+ transition :parked => :idling
233
+ end
234
+ @machine.event :shift_up do
235
+ transition :parked => :idling, :idling => :first_gear
236
+ end
237
+ @machine.event :shift_down do
238
+ transition :first_gear => :idling
239
+ end
240
+ @object = @klass.new
241
+ @object.state = 'parked'
242
+
243
+ @paths = StateMachine::PathCollection.new(@object, @machine, :to => :idling, :deep => true)
244
+ end
245
+
246
+ def test_should_allow_target_to_be_reached_more_than_once_per_path
247
+ assert_equal [
248
+ [
249
+ StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
250
+ ],
251
+ [
252
+ StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
253
+ StateMachine::Transition.new(@object, @machine, :shift_up, :idling, :first_gear),
254
+ StateMachine::Transition.new(@object, @machine, :shift_down, :first_gear, :idling)
255
+ ],
256
+ [
257
+ StateMachine::Transition.new(@object, @machine, :shift_up, :parked, :idling)
258
+ ],
259
+ [
260
+ StateMachine::Transition.new(@object, @machine, :shift_up, :parked, :idling),
261
+ StateMachine::Transition.new(@object, @machine, :shift_up, :idling, :first_gear),
262
+ StateMachine::Transition.new(@object, @machine, :shift_down, :first_gear, :idling)
263
+ ]
264
+ ], @paths
265
+ end
266
+ end
@@ -0,0 +1,485 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class PathByDefaultTest < Test::Unit::TestCase
4
+ def setup
5
+ @klass = Class.new
6
+ @machine = StateMachine::Machine.new(@klass)
7
+ @object = @klass.new
8
+
9
+ @path = StateMachine::Path.new(@object, @machine)
10
+ end
11
+
12
+ def test_should_have_an_object
13
+ assert_equal @object, @path.object
14
+ end
15
+
16
+ def test_should_have_a_machine
17
+ assert_equal @machine, @path.machine
18
+ end
19
+
20
+ def test_should_not_have_walked_anywhere
21
+ assert_equal [], @path
22
+ end
23
+
24
+ def test_should_not_have_a_from_name
25
+ assert_nil @path.from_name
26
+ end
27
+
28
+ def test_should_have_no_from_states
29
+ assert_equal [], @path.from_states
30
+ end
31
+
32
+ def test_should_not_have_a_to_name
33
+ assert_nil @path.to_name
34
+ end
35
+
36
+ def test_should_have_no_to_states
37
+ assert_equal [], @path.to_states
38
+ end
39
+
40
+ def test_should_have_no_events
41
+ assert_equal [], @path.events
42
+ end
43
+
44
+ def test_should_not_be_able_to_walk_anywhere
45
+ walked = false
46
+ @path.walk { walked = true }
47
+ assert_equal false, walked
48
+ end
49
+
50
+ def test_should_not_be_complete
51
+ assert_equal false, @path.complete?
52
+ end
53
+ end
54
+
55
+ class PathTest < Test::Unit::TestCase
56
+ def setup
57
+ @klass = Class.new
58
+ @machine = StateMachine::Machine.new(@klass)
59
+ @object = @klass.new
60
+ end
61
+
62
+ def test_should_raise_exception_if_invalid_option_specified
63
+ exception = assert_raise(ArgumentError) {StateMachine::Path.new(@object, @machine, :invalid => true)}
64
+ assert_equal 'Invalid key(s): invalid', exception.message
65
+ end
66
+ end
67
+
68
+ class PathWithoutTransitionsTest < Test::Unit::TestCase
69
+ def setup
70
+ @klass = Class.new
71
+ @machine = StateMachine::Machine.new(@klass)
72
+ @machine.state :parked, :idling
73
+ @machine.event :ignite
74
+
75
+ @object = @klass.new
76
+
77
+ @path = StateMachine::Path.new(@object, @machine)
78
+ @path.concat([
79
+ @ignite_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
80
+ ])
81
+ end
82
+
83
+ def test_should_not_be_able_to_walk_anywhere
84
+ walked = false
85
+ @path.walk { walked = true }
86
+ assert_equal false, walked
87
+ end
88
+ end
89
+
90
+ class PathWithTransitionsTest < Test::Unit::TestCase
91
+ def setup
92
+ @klass = Class.new
93
+ @machine = StateMachine::Machine.new(@klass)
94
+ @machine.state :parked, :idling, :first_gear
95
+ @machine.event :ignite, :shift_up
96
+
97
+ @object = @klass.new
98
+ @object.state = 'parked'
99
+
100
+ @path = StateMachine::Path.new(@object, @machine)
101
+ @path.concat([
102
+ @ignite_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
103
+ @shift_up_transition = StateMachine::Transition.new(@object, @machine, :shift_up, :idling, :first_gear)
104
+ ])
105
+ end
106
+
107
+ def test_should_enumerate_transitions
108
+ assert_equal [@ignite_transition, @shift_up_transition], @path
109
+ end
110
+
111
+ def test_should_have_a_from_name
112
+ assert_equal :parked, @path.from_name
113
+ end
114
+
115
+ def test_should_have_from_states
116
+ assert_equal [:parked, :idling], @path.from_states
117
+ end
118
+
119
+ def test_should_have_a_to_name
120
+ assert_equal :first_gear, @path.to_name
121
+ end
122
+
123
+ def test_should_have_to_states
124
+ assert_equal [:idling, :first_gear], @path.to_states
125
+ end
126
+
127
+ def test_should_have_events
128
+ assert_equal [:ignite, :shift_up], @path.events
129
+ end
130
+
131
+ def test_should_not_be_able_to_walk_anywhere
132
+ walked = false
133
+ @path.walk { walked = true }
134
+ assert_equal false, walked
135
+ end
136
+
137
+ def test_should_be_complete
138
+ assert_equal true, @path.complete?
139
+ end
140
+ end
141
+
142
+ class PathWithDuplicatesTest < Test::Unit::TestCase
143
+ def setup
144
+ @klass = Class.new
145
+ @machine = StateMachine::Machine.new(@klass)
146
+ @machine.state :parked, :idling
147
+ @machine.event :park, :ignite
148
+
149
+ @object = @klass.new
150
+ @object.state = 'parked'
151
+
152
+ @path = StateMachine::Path.new(@object, @machine)
153
+ @path.concat([
154
+ @ignite_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
155
+ @park_transition = StateMachine::Transition.new(@object, @machine, :park, :idling, :parked),
156
+ @ignite_again_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
157
+ ])
158
+ end
159
+
160
+ def test_should_not_include_duplicates_in_from_states
161
+ assert_equal [:parked, :idling], @path.from_states
162
+ end
163
+
164
+ def test_should_not_include_duplicates_in_to_states
165
+ assert_equal [:idling, :parked], @path.to_states
166
+ end
167
+
168
+ def test_should_not_include_duplicates_in_events
169
+ assert_equal [:ignite, :park], @path.events
170
+ end
171
+ end
172
+
173
+ class PathWithAvailableTransitionsTest < Test::Unit::TestCase
174
+ def setup
175
+ @klass = Class.new
176
+ @machine = StateMachine::Machine.new(@klass)
177
+ @machine.state :parked, :idling, :first_gear
178
+ @machine.event :ignite
179
+ @machine.event :shift_up do
180
+ transition :idling => :first_gear
181
+ end
182
+ @machine.event :park do
183
+ transition :idling => :parked
184
+ end
185
+
186
+ @object = @klass.new
187
+ @object.state = 'parked'
188
+
189
+ @path = StateMachine::Path.new(@object, @machine)
190
+ @path.concat([
191
+ @ignite_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
192
+ ])
193
+ end
194
+
195
+ def test_should_not_be_complete
196
+ assert !@path.complete?
197
+ end
198
+
199
+ def test_should_walk_each_available_transition
200
+ paths = []
201
+ @path.walk {|path| paths << path}
202
+
203
+ assert_equal [
204
+ [@ignite_transition, StateMachine::Transition.new(@object, @machine, :shift_up, :idling, :first_gear)],
205
+ [@ignite_transition, StateMachine::Transition.new(@object, @machine, :park, :idling, :parked)]
206
+ ], paths
207
+ end
208
+
209
+ def test_should_yield_path_instances_when_walking
210
+ @path.walk do |path|
211
+ assert_instance_of StateMachine::Path, path
212
+ end
213
+ end
214
+
215
+ def test_should_not_modify_current_path_after_walking
216
+ @path.walk {}
217
+ assert_equal [@ignite_transition], @path
218
+ end
219
+
220
+ def test_should_not_modify_object_after_walking
221
+ @path.walk {}
222
+ assert_equal 'parked', @object.state
223
+ end
224
+ end
225
+
226
+ class PathWithGuardedTransitionsTest < Test::Unit::TestCase
227
+ def setup
228
+ @klass = Class.new
229
+ @machine = StateMachine::Machine.new(@klass)
230
+ @machine.state :parked, :idling
231
+ @machine.event :ignite
232
+ @machine.event :shift_up do
233
+ transition :idling => :first_gear, :if => lambda {false}
234
+ end
235
+
236
+ @object = @klass.new
237
+ @object.state = 'parked'
238
+ end
239
+
240
+ def test_should_not_walk_transitions_if_guard_enabled
241
+ path = StateMachine::Path.new(@object, @machine)
242
+ path.concat([
243
+ StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
244
+ ])
245
+
246
+ paths = []
247
+ path.walk {|next_path| paths << next_path}
248
+
249
+ assert_equal [], paths
250
+ end
251
+
252
+ def test_should_not_walk_transitions_if_guard_disabled
253
+ path = StateMachine::Path.new(@object, @machine, :guard => false)
254
+ path.concat([
255
+ ignite_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
256
+ ])
257
+
258
+ paths = []
259
+ path.walk {|next_path| paths << next_path}
260
+
261
+ assert_equal [
262
+ [ignite_transition, StateMachine::Transition.new(@object, @machine, :shift_up, :idling, :first_gear)]
263
+ ], paths
264
+ end
265
+ end
266
+
267
+ class PathWithEncounteredTransitionsTest < Test::Unit::TestCase
268
+ def setup
269
+ @klass = Class.new
270
+ @machine = StateMachine::Machine.new(@klass)
271
+ @machine.state :parked, :idling, :first_gear
272
+ @machine.event :ignite do
273
+ transition :parked => :idling
274
+ end
275
+ @machine.event :park do
276
+ transition :idling => :parked
277
+ end
278
+
279
+ @object = @klass.new
280
+ @object.state = 'parked'
281
+
282
+ @path = StateMachine::Path.new(@object, @machine)
283
+ @path.concat([
284
+ @ignite_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
285
+ @park_transition = StateMachine::Transition.new(@object, @machine, :park, :idling, :parked)
286
+ ])
287
+ end
288
+
289
+ def test_should_be_complete
290
+ assert_equal true, @path.complete?
291
+ end
292
+
293
+ def test_should_not_be_able_to_walk
294
+ walked = false
295
+ @path.walk { walked = true }
296
+ assert_equal false, walked
297
+ end
298
+ end
299
+
300
+ class PathWithUnreachedTargetTest < Test::Unit::TestCase
301
+ def setup
302
+ @klass = Class.new
303
+ @machine = StateMachine::Machine.new(@klass)
304
+ @machine.state :parked, :idling
305
+ @machine.event :ignite do
306
+ transition :parked => :idling
307
+ end
308
+
309
+ @object = @klass.new
310
+ @object.state = 'parked'
311
+
312
+ @path = StateMachine::Path.new(@object, @machine, :target => :parked)
313
+ @path.concat([
314
+ @ignite_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
315
+ ])
316
+ end
317
+
318
+ def test_should_not_be_complete
319
+ assert_equal false, @path.complete?
320
+ end
321
+
322
+ def test_should_not_be_able_to_walk
323
+ walked = false
324
+ @path.walk { walked = true }
325
+ assert_equal false, walked
326
+ end
327
+ end
328
+
329
+ class PathWithReachedTargetTest < Test::Unit::TestCase
330
+ def setup
331
+ @klass = Class.new
332
+ @machine = StateMachine::Machine.new(@klass)
333
+ @machine.state :parked, :idling
334
+ @machine.event :ignite do
335
+ transition :parked => :idling
336
+ end
337
+ @machine.event :park do
338
+ transition :idling => :parked
339
+ end
340
+
341
+ @object = @klass.new
342
+ @object.state = 'parked'
343
+
344
+ @path = StateMachine::Path.new(@object, @machine, :target => :parked)
345
+ @path.concat([
346
+ @ignite_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
347
+ @park_transition = StateMachine::Transition.new(@object, @machine, :park, :idling, :parked)
348
+ ])
349
+ end
350
+
351
+ def test_should_be_complete
352
+ assert_equal true, @path.complete?
353
+ end
354
+
355
+ def test_should_not_be_able_to_walk
356
+ walked = false
357
+ @path.walk { walked = true }
358
+ assert_equal false, walked
359
+ end
360
+ end
361
+
362
+ class PathWithAvailableTransitionsAfterReachingTargetTest < Test::Unit::TestCase
363
+ def setup
364
+ @klass = Class.new
365
+ @machine = StateMachine::Machine.new(@klass)
366
+ @machine.state :parked, :idling
367
+ @machine.event :ignite do
368
+ transition :parked => :idling
369
+ end
370
+ @machine.event :shift_up do
371
+ transition :parked => :first_gear
372
+ end
373
+ @machine.event :park do
374
+ transition [:idling, :first_gear] => :parked
375
+ end
376
+
377
+ @object = @klass.new
378
+ @object.state = 'parked'
379
+
380
+ @path = StateMachine::Path.new(@object, @machine, :target => :parked)
381
+ @path.concat([
382
+ @ignite_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
383
+ @park_transition = StateMachine::Transition.new(@object, @machine, :park, :idling, :parked)
384
+ ])
385
+ end
386
+
387
+ def test_should_be_complete
388
+ assert_equal true, @path.complete?
389
+ end
390
+
391
+ def test_should_be_able_to_walk
392
+ paths = []
393
+ @path.walk {|path| paths << path}
394
+ assert_equal [
395
+ [@ignite_transition, @park_transition, StateMachine::Transition.new(@object, @machine, :shift_up, :parked, :first_gear)]
396
+ ], paths
397
+ end
398
+ end
399
+
400
+ class PathWithDeepTargetTest < Test::Unit::TestCase
401
+ def setup
402
+ @klass = Class.new
403
+ @machine = StateMachine::Machine.new(@klass)
404
+ @machine.state :parked, :idling
405
+ @machine.event :ignite do
406
+ transition :parked => :idling
407
+ end
408
+ @machine.event :shift_up do
409
+ transition :parked => :first_gear
410
+ end
411
+ @machine.event :park do
412
+ transition [:idling, :first_gear] => :parked
413
+ end
414
+
415
+ @object = @klass.new
416
+ @object.state = 'parked'
417
+
418
+ @path = StateMachine::Path.new(@object, @machine, :target => :parked)
419
+ @path.concat([
420
+ @ignite_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
421
+ @park_transition = StateMachine::Transition.new(@object, @machine, :park, :idling, :parked),
422
+ @shift_up_transition = StateMachine::Transition.new(@object, @machine, :shift_up, :parked, :first_gear)
423
+ ])
424
+ end
425
+
426
+ def test_should_not_be_complete
427
+ assert_equal false, @path.complete?
428
+ end
429
+
430
+ def test_should_be_able_to_walk
431
+ paths = []
432
+ @path.walk {|path| paths << path}
433
+ assert_equal [
434
+ [@ignite_transition, @park_transition, @shift_up_transition, StateMachine::Transition.new(@object, @machine, :park, :first_gear, :parked)]
435
+ ], paths
436
+ end
437
+ end
438
+
439
+ class PathWithDeepTargetReachedTest < Test::Unit::TestCase
440
+ def setup
441
+ @klass = Class.new
442
+ @machine = StateMachine::Machine.new(@klass)
443
+ @machine.state :parked, :idling
444
+ @machine.event :ignite do
445
+ transition :parked => :idling
446
+ end
447
+ @machine.event :shift_up do
448
+ transition :parked => :first_gear
449
+ end
450
+ @machine.event :park do
451
+ transition [:idling, :first_gear] => :parked
452
+ end
453
+
454
+ @object = @klass.new
455
+ @object.state = 'parked'
456
+
457
+ @path = StateMachine::Path.new(@object, @machine, :target => :parked)
458
+ @path.concat([
459
+ @ignite_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
460
+ @park_transition = StateMachine::Transition.new(@object, @machine, :park, :idling, :parked),
461
+ @shift_up_transition = StateMachine::Transition.new(@object, @machine, :shift_up, :parked, :first_gear),
462
+ @park_transition_2 = StateMachine::Transition.new(@object, @machine, :park, :first_gear, :parked)
463
+ ])
464
+ end
465
+
466
+ def test_should_be_complete
467
+ assert_equal true, @path.complete?
468
+ end
469
+
470
+ def test_should_not_be_able_to_walk
471
+ walked = false
472
+ @path.walk { walked = true }
473
+ assert_equal false, walked
474
+ end
475
+
476
+ def test_should_not_be_able_to_walk_with_available_transitions
477
+ @machine.event :park do
478
+ transition :parked => same
479
+ end
480
+
481
+ walked = false
482
+ @path.walk { walked = true }
483
+ assert_equal false, walked
484
+ end
485
+ end