state_machines 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (465) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +10 -4
  3. data/Changelog.md +0 -0
  4. data/Gemfile +6 -0
  5. data/LICENSE.txt +1 -1
  6. data/README.md +6 -8
  7. data/Rakefile +9 -6
  8. data/Testing.md +0 -0
  9. data/lib/state_machines/assertions.rb +5 -5
  10. data/lib/state_machines/error.rb +2 -1
  11. data/lib/state_machines/integrations.rb +18 -11
  12. data/lib/state_machines/machine.rb +8 -12
  13. data/lib/state_machines/version.rb +1 -1
  14. data/state_machines.gemspec +6 -8
  15. data/test/files/integrations/event_on_failure_integration.rb +10 -0
  16. data/test/files/integrations/vehicle.rb +7 -0
  17. data/{spec/internal/app → test/files}/models/auto_shop.rb +0 -0
  18. data/{spec/internal/app → test/files}/models/car.rb +2 -0
  19. data/{spec/internal/app → test/files}/models/model_base.rb +0 -0
  20. data/{spec/internal/app → test/files}/models/motorcycle.rb +2 -0
  21. data/{spec/internal/app → test/files}/models/traffic_light.rb +2 -2
  22. data/{spec/internal/app → test/files}/models/vehicle.rb +9 -5
  23. data/test/files/node.rb +5 -0
  24. data/test/files/switch.rb +15 -0
  25. data/test/functional/auto_shop_available_test.rb +20 -0
  26. data/test/functional/auto_shop_busy_test.rb +25 -0
  27. data/test/functional/car_backing_up_test.rb +45 -0
  28. data/test/functional/car_test.rb +49 -0
  29. data/test/functional/motorcycle_test.rb +46 -0
  30. data/test/functional/traffic_light_caution_test.rb +17 -0
  31. data/test/functional/traffic_light_proceed_test.rb +17 -0
  32. data/test/functional/traffic_light_stop_test.rb +26 -0
  33. data/test/functional/vehicle_first_gear_test.rb +42 -0
  34. data/test/functional/vehicle_idling_test.rb +59 -0
  35. data/test/functional/vehicle_locked_test.rb +29 -0
  36. data/test/functional/vehicle_parked_test.rb +53 -0
  37. data/test/functional/vehicle_repaired_test.rb +20 -0
  38. data/test/functional/vehicle_second_gear_test.rb +42 -0
  39. data/test/functional/vehicle_stalled_test.rb +65 -0
  40. data/test/functional/vehicle_test.rb +20 -0
  41. data/test/functional/vehicle_third_gear_test.rb +42 -0
  42. data/test/functional/vehicle_unsaved_test.rb +181 -0
  43. data/test/functional/vehicle_with_event_attributes_test.rb +30 -0
  44. data/test/functional/vehicle_with_parallel_events_test.rb +36 -0
  45. data/test/test_helper.rb +15 -0
  46. data/test/unit/assertions/assert_exclusive_keys_test.rb +22 -0
  47. data/test/unit/assertions/assert_valid_key_test.rb +12 -0
  48. data/test/unit/branch/branch_test.rb +28 -0
  49. data/test/unit/branch/branch_with_conflicting_conditionals_test.rb +27 -0
  50. data/test/unit/branch/branch_with_conflicting_from_requirements_test.rb +8 -0
  51. data/test/unit/branch/branch_with_conflicting_on_requirements_test.rb +8 -0
  52. data/test/unit/branch/branch_with_conflicting_to_requirements_test.rb +8 -0
  53. data/test/unit/branch/branch_with_different_requirements_test.rb +41 -0
  54. data/test/unit/branch/branch_with_except_from_matcher_requirement_test.rb +8 -0
  55. data/test/unit/branch/branch_with_except_from_requirement_test.rb +36 -0
  56. data/test/unit/branch/branch_with_except_on_matcher_requirement_test.rb +8 -0
  57. data/test/unit/branch/branch_with_except_on_requirement_test.rb +36 -0
  58. data/test/unit/branch/branch_with_except_to_matcher_requirement_test.rb +8 -0
  59. data/test/unit/branch/branch_with_except_to_requirement_test.rb +36 -0
  60. data/test/unit/branch/branch_with_from_matcher_requirement_test.rb +20 -0
  61. data/test/unit/branch/branch_with_from_requirement_test.rb +45 -0
  62. data/test/unit/branch/branch_with_if_conditional_test.rb +27 -0
  63. data/test/unit/branch/branch_with_implicit_and_explicit_requirements_test.rb +23 -0
  64. data/test/unit/branch/branch_with_implicit_from_requirement_matcher_test.rb +20 -0
  65. data/test/unit/branch/branch_with_implicit_requirement_test.rb +20 -0
  66. data/test/unit/branch/branch_with_implicit_to_requirement_matcher_test.rb +16 -0
  67. data/test/unit/branch/branch_with_multiple_except_from_requirements_test.rb +20 -0
  68. data/test/unit/branch/branch_with_multiple_except_on_requirements_test.rb +16 -0
  69. data/test/unit/branch/branch_with_multiple_except_to_requirements_test.rb +20 -0
  70. data/test/unit/branch/branch_with_multiple_from_requirements_test.rb +16 -0
  71. data/test/unit/branch/branch_with_multiple_if_conditionals_test.rb +20 -0
  72. data/test/unit/branch/branch_with_multiple_implicit_requirements_test.rb +53 -0
  73. data/test/unit/branch/branch_with_multiple_on_requirements_test.rb +20 -0
  74. data/test/unit/branch/branch_with_multiple_to_requirements_test.rb +20 -0
  75. data/test/unit/branch/branch_with_multiple_unless_conditionals_test.rb +20 -0
  76. data/test/unit/branch/branch_with_nil_requirements_test.rb +28 -0
  77. data/test/unit/branch/branch_with_no_requirements_test.rb +36 -0
  78. data/test/unit/branch/branch_with_on_matcher_requirement_test.rb +16 -0
  79. data/test/unit/branch/branch_with_on_requirement_test.rb +45 -0
  80. data/test/unit/branch/branch_with_to_matcher_requirement_test.rb +20 -0
  81. data/test/unit/branch/branch_with_to_requirement_test.rb +45 -0
  82. data/test/unit/branch/branch_with_unless_conditional_test.rb +27 -0
  83. data/test/unit/branch/branch_without_guards_test.rb +27 -0
  84. data/test/unit/callback/callback_by_default_test.rb +25 -0
  85. data/test/unit/callback/callback_test.rb +53 -0
  86. data/test/unit/callback/callback_with_application_bound_object_test.rb +23 -0
  87. data/test/unit/callback/callback_with_application_terminator_test.rb +24 -0
  88. data/test/unit/callback/callback_with_arguments_test.rb +14 -0
  89. data/test/unit/callback/callback_with_around_type_and_arguments_test.rb +25 -0
  90. data/test/unit/callback/callback_with_around_type_and_block_test.rb +44 -0
  91. data/test/unit/callback/callback_with_around_type_and_bound_method_test.rb +23 -0
  92. data/test/unit/callback/callback_with_around_type_and_multiple_methods_test.rb +93 -0
  93. data/test/unit/callback/callback_with_around_type_and_terminator_test.rb +17 -0
  94. data/test/unit/callback/callback_with_block_test.rb +20 -0
  95. data/test/unit/callback/callback_with_bound_method_and_arguments_test.rb +28 -0
  96. data/test/unit/callback/callback_with_bound_method_test.rb +35 -0
  97. data/test/unit/callback/callback_with_do_method_test.rb +18 -0
  98. data/test/unit/callback/callback_with_explicit_requirements_test.rb +32 -0
  99. data/test/unit/callback/callback_with_if_condition_test.rb +17 -0
  100. data/test/unit/callback/callback_with_implicit_requirements_test.rb +32 -0
  101. data/test/unit/callback/callback_with_method_argument_test.rb +18 -0
  102. data/test/unit/callback/callback_with_mixed_methods_test.rb +31 -0
  103. data/test/unit/callback/callback_with_multiple_bound_methods_test.rb +21 -0
  104. data/test/unit/callback/callback_with_multiple_do_methods_test.rb +29 -0
  105. data/test/unit/callback/callback_with_multiple_method_arguments_test.rb +29 -0
  106. data/test/unit/callback/callback_with_terminator_test.rb +22 -0
  107. data/test/unit/callback/callback_with_unbound_method_test.rb +14 -0
  108. data/test/unit/callback/callback_with_unless_condition_test.rb +17 -0
  109. data/test/unit/callback/callback_without_arguments_test.rb +14 -0
  110. data/test/unit/callback/callback_without_terminator_test.rb +12 -0
  111. data/test/unit/error/error_by_default_test.rb +21 -0
  112. data/test/unit/error/error_with_message_test.rb +23 -0
  113. data/test/unit/eval_helper/eval_helpers_base_test.rb +8 -0
  114. data/test/unit/eval_helper/eval_helpers_proc_block_and_explicit_arguments_test.rb +14 -0
  115. data/test/unit/eval_helper/eval_helpers_proc_block_and_implicit_arguments_test.rb +14 -0
  116. data/test/unit/eval_helper/eval_helpers_proc_test.rb +13 -0
  117. data/test/unit/eval_helper/eval_helpers_proc_with_arguments_test.rb +13 -0
  118. data/test/unit/eval_helper/eval_helpers_proc_with_block_test.rb +13 -0
  119. data/test/unit/eval_helper/eval_helpers_proc_with_block_without_arguments_test.rb +18 -0
  120. data/test/unit/eval_helper/eval_helpers_proc_with_block_without_object_test.rb +14 -0
  121. data/test/unit/eval_helper/eval_helpers_proc_without_arguments_test.rb +19 -0
  122. data/test/unit/eval_helper/eval_helpers_string_test.rb +25 -0
  123. data/test/unit/eval_helper/eval_helpers_string_with_block_test.rb +12 -0
  124. data/test/unit/eval_helper/eval_helpers_symbol_method_missing_test.rb +20 -0
  125. data/test/unit/eval_helper/eval_helpers_symbol_private_test.rb +17 -0
  126. data/test/unit/eval_helper/eval_helpers_symbol_protected_test.rb +17 -0
  127. data/test/unit/eval_helper/eval_helpers_symbol_tainted_method_test.rb +18 -0
  128. data/test/unit/eval_helper/eval_helpers_symbol_test.rb +16 -0
  129. data/test/unit/eval_helper/eval_helpers_symbol_with_arguments_and_block_test.rb +16 -0
  130. data/test/unit/eval_helper/eval_helpers_symbol_with_arguments_test.rb +16 -0
  131. data/test/unit/eval_helper/eval_helpers_symbol_with_block_test.rb +16 -0
  132. data/test/unit/eval_helper/eval_helpers_test.rb +13 -0
  133. data/test/unit/event/event_after_being_copied_test.rb +17 -0
  134. data/test/unit/event/event_by_default_test.rb +60 -0
  135. data/test/unit/event/event_context_test.rb +16 -0
  136. data/test/unit/event/event_on_failure_test.rb +44 -0
  137. data/test/unit/event/event_test.rb +34 -0
  138. data/test/unit/event/event_transitions_test.rb +62 -0
  139. data/test/unit/event/event_with_conflicting_helpers_after_definition_test.rb +79 -0
  140. data/test/unit/event/event_with_conflicting_helpers_before_definition_test.rb +58 -0
  141. data/test/unit/event/event_with_conflicting_machine_test.rb +48 -0
  142. data/test/unit/event/event_with_dynamic_human_name_test.rb +26 -0
  143. data/test/unit/event/event_with_human_name_test.rb +13 -0
  144. data/test/unit/event/event_with_invalid_current_state_test.rb +30 -0
  145. data/test/unit/event/event_with_machine_action_test.rb +33 -0
  146. data/test/unit/event/event_with_marshalling_test.rb +47 -0
  147. data/test/unit/event/event_with_matching_disabled_transitions_test.rb +115 -0
  148. data/test/unit/event/event_with_matching_enabled_transitions_test.rb +75 -0
  149. data/test/unit/event/event_with_multiple_transitions_test.rb +61 -0
  150. data/test/unit/event/event_with_namespace_test.rb +34 -0
  151. data/test/unit/event/event_with_transition_with_blacklisted_to_state_test.rb +60 -0
  152. data/test/unit/event/event_with_transition_with_loopback_state_test.rb +36 -0
  153. data/test/unit/event/event_with_transition_with_nil_to_state_test.rb +36 -0
  154. data/test/unit/event/event_with_transition_with_whitelisted_to_state_test.rb +51 -0
  155. data/test/unit/event/event_with_transition_without_to_state_test.rb +36 -0
  156. data/test/unit/event/event_with_transitions_test.rb +32 -0
  157. data/test/unit/event/event_without_matching_transitions_test.rb +41 -0
  158. data/test/unit/event/event_without_transitions_test.rb +28 -0
  159. data/{spec/state_machines/invalid_event_spec.rb → test/unit/event/invalid_event_test.rb} +8 -7
  160. data/test/unit/event_collection/event_collection_attribute_with_machine_action_test.rb +62 -0
  161. data/test/unit/event_collection/event_collection_attribute_with_namespaced_machine_test.rb +36 -0
  162. data/test/unit/event_collection/event_collection_by_default_test.rb +26 -0
  163. data/test/unit/event_collection/event_collection_test.rb +39 -0
  164. data/test/unit/event_collection/event_collection_with_custom_machine_attribute_test.rb +31 -0
  165. data/test/unit/event_collection/event_collection_with_events_with_transitions_test.rb +76 -0
  166. data/test/unit/event_collection/event_collection_with_multiple_events_test.rb +27 -0
  167. data/test/unit/event_collection/event_collection_with_validations_test.rb +75 -0
  168. data/test/unit/event_collection/event_collection_without_machine_action_test.rb +18 -0
  169. data/test/unit/event_collection/event_string_collection_test.rb +31 -0
  170. data/test/unit/helper_module_test.rb +17 -0
  171. data/test/unit/integrations/integration_finder_test.rb +16 -0
  172. data/test/unit/integrations/integration_matcher_test.rb +27 -0
  173. data/test/unit/invalid_transition/invalid_parallel_transition_test.rb +18 -0
  174. data/test/unit/invalid_transition/invalid_transition_test.rb +47 -0
  175. data/test/unit/invalid_transition/invalid_transition_with_integration_test.rb +47 -0
  176. data/test/unit/invalid_transition/invalid_transition_with_namespace_test.rb +32 -0
  177. data/test/unit/machine/machine_after_being_copied_test.rb +62 -0
  178. data/test/unit/machine/machine_after_changing_initial_state.rb +28 -0
  179. data/test/unit/machine/machine_after_changing_owner_class_test.rb +31 -0
  180. data/test/unit/machine/machine_by_default_test.rb +160 -0
  181. data/test/unit/machine/machine_finder_custom_options_test.rb +17 -0
  182. data/test/unit/machine/machine_finder_with_existing_machine_on_superclass_test.rb +86 -0
  183. data/test/unit/machine/machine_finder_with_existing_on_same_class_test.rb +23 -0
  184. data/test/unit/machine/machine_finder_without_existing_machine_test.rb +25 -0
  185. data/test/unit/machine/machine_persistence_test.rb +52 -0
  186. data/test/unit/machine/machine_state_initialization_test.rb +56 -0
  187. data/test/unit/machine/machine_test.rb +30 -0
  188. data/test/unit/machine/machine_with_action_already_overridden_test.rb +23 -0
  189. data/test/unit/machine/machine_with_action_defined_in_class_test.rb +37 -0
  190. data/test/unit/machine/machine_with_action_defined_in_included_module_test.rb +46 -0
  191. data/test/unit/machine/machine_with_action_defined_in_superclass_test.rb +43 -0
  192. data/test/unit/machine/machine_with_action_undefined_test.rb +33 -0
  193. data/test/unit/machine/machine_with_cached_state_test.rb +20 -0
  194. data/test/unit/machine/machine_with_class_helpers_test.rb +179 -0
  195. data/test/unit/machine/machine_with_conflicting_helpers_after_definition_test.rb +243 -0
  196. data/test/unit/machine/machine_with_conflicting_helpers_before_definition_test.rb +175 -0
  197. data/test/unit/machine/machine_with_custom_action_test.rb +11 -0
  198. data/test/unit/machine/machine_with_custom_attribute_test.rb +103 -0
  199. data/test/unit/machine/machine_with_custom_initialize_test.rb +24 -0
  200. data/test/unit/machine/machine_with_custom_integration_test.rb +69 -0
  201. data/test/unit/machine/machine_with_custom_invalidation_test.rb +40 -0
  202. data/test/unit/machine/machine_with_custom_name_test.rb +57 -0
  203. data/test/unit/machine/machine_with_custom_plural_test.rb +53 -0
  204. data/test/unit/machine/machine_with_dynamic_initial_state_test.rb +65 -0
  205. data/test/unit/machine/machine_with_event_matchers_test.rb +41 -0
  206. data/test/unit/machine/machine_with_events_test.rb +52 -0
  207. data/test/unit/machine/machine_with_events_with_custom_human_names_test.rb +18 -0
  208. data/test/unit/machine/machine_with_events_with_transitions_test.rb +37 -0
  209. data/test/unit/machine/machine_with_existing_event_test.rb +17 -0
  210. data/test/unit/machine/machine_with_existing_machines_on_owner_class_test.rb +20 -0
  211. data/test/unit/machine/machine_with_existing_machines_with_same_attributes_on_owner_class_test.rb +71 -0
  212. data/test/unit/machine/machine_with_existing_machines_with_same_attributes_on_owner_subclass_test.rb +31 -0
  213. data/test/unit/machine/machine_with_existing_state_test.rb +27 -0
  214. data/test/unit/machine/machine_with_failure_callbacks_test.rb +48 -0
  215. data/test/unit/machine/machine_with_helpers_test.rb +14 -0
  216. data/test/unit/machine/machine_with_initial_state_with_value_and_owner_default.rb +25 -0
  217. data/test/unit/machine/machine_with_initialize_and_super_test.rb +17 -0
  218. data/test/unit/machine/machine_with_initialize_arguments_and_block_test.rb +31 -0
  219. data/test/unit/machine/machine_with_initialize_without_super_test.rb +17 -0
  220. data/test/unit/machine/machine_with_instance_helpers_test.rb +179 -0
  221. data/test/unit/machine/machine_with_integration_test.rb +71 -0
  222. data/test/unit/machine/machine_with_multiple_events_test.rb +32 -0
  223. data/test/unit/machine/machine_with_namespace_test.rb +48 -0
  224. data/test/unit/machine/machine_with_nil_action_test.rb +24 -0
  225. data/test/unit/machine/machine_with_other_states.rb +22 -0
  226. data/test/unit/machine/machine_with_owner_subclass_test.rb +18 -0
  227. data/test/unit/machine/machine_with_paths_test.rb +25 -0
  228. data/test/unit/machine/machine_with_private_action_test.rb +43 -0
  229. data/test/unit/machine/machine_with_state_matchers_test.rb +41 -0
  230. data/test/unit/machine/machine_with_state_with_matchers_test.rb +19 -0
  231. data/test/unit/machine/machine_with_states_test.rb +55 -0
  232. data/test/unit/machine/machine_with_states_with_behaviors_test.rb +23 -0
  233. data/test/unit/machine/machine_with_states_with_custom_human_names_test.rb +18 -0
  234. data/test/unit/machine/machine_with_states_with_custom_values_test.rb +21 -0
  235. data/test/unit/machine/machine_with_states_with_runtime_dependencies_test.rb +19 -0
  236. data/test/unit/machine/machine_with_static_initial_state_test.rb +60 -0
  237. data/test/unit/machine/machine_with_superclass_conflicting_helpers_after_definition_test.rb +36 -0
  238. data/test/unit/machine/machine_with_transition_callbacks_test.rb +144 -0
  239. data/test/unit/machine/machine_with_transitions_test.rb +87 -0
  240. data/test/unit/machine/machine_without_initialization_test.rb +31 -0
  241. data/test/unit/machine/machine_without_initialize_test.rb +14 -0
  242. data/test/unit/machine/machine_without_integration_test.rb +31 -0
  243. data/test/unit/machine_collection/machine_collection_by_default_test.rb +11 -0
  244. data/test/unit/machine_collection/machine_collection_fire_attributes_with_validations_test.rb +72 -0
  245. data/test/unit/machine_collection/machine_collection_fire_test.rb +80 -0
  246. data/test/unit/machine_collection/machine_collection_fire_with_transactions_test.rb +54 -0
  247. data/test/unit/machine_collection/machine_collection_fire_with_validations_test.rb +76 -0
  248. data/test/unit/machine_collection/machine_collection_state_initialization_test.rb +101 -0
  249. data/test/unit/machine_collection/machine_collection_transitions_with_blank_events_test.rb +25 -0
  250. data/test/unit/machine_collection/machine_collection_transitions_with_custom_options_test.rb +20 -0
  251. data/test/unit/machine_collection/machine_collection_transitions_with_different_actions_test.rb +26 -0
  252. data/test/unit/machine_collection/machine_collection_transitions_with_exisiting_transitions_test.rb +25 -0
  253. data/test/unit/machine_collection/machine_collection_transitions_with_invalid_events_test.rb +25 -0
  254. data/test/unit/machine_collection/machine_collection_transitions_with_same_actions_test.rb +31 -0
  255. data/test/unit/machine_collection/machine_collection_transitions_with_transition_test.rb +26 -0
  256. data/test/unit/machine_collection/machine_collection_transitions_without_events_test.rb +25 -0
  257. data/test/unit/machine_collection/machine_collection_transitions_without_transition_test.rb +27 -0
  258. data/test/unit/matcher/all_matcher_test.rb +29 -0
  259. data/test/unit/matcher/blacklist_matcher_test.rb +30 -0
  260. data/test/unit/matcher/loopback_matcher_test.rb +27 -0
  261. data/test/unit/matcher/matcher_by_default_test.rb +15 -0
  262. data/test/unit/matcher/matcher_with_multiple_values_test.rb +15 -0
  263. data/test/unit/matcher/matcher_with_value_test.rb +15 -0
  264. data/test/unit/matcher/whitelist_matcher_test.rb +30 -0
  265. data/test/unit/matcher_helpers/matcher_helpers_all_test.rb +14 -0
  266. data/test/unit/matcher_helpers/matcher_helpers_any_test.rb +14 -0
  267. data/test/unit/matcher_helpers/matcher_helpers_same_test.rb +13 -0
  268. data/test/unit/node_collection/node_collection_after_being_copied_test/n.rb +46 -0
  269. data/test/unit/node_collection/node_collection_after_update_test/n.rb +36 -0
  270. data/test/unit/node_collection/node_collection_by_default_test.rb +22 -0
  271. data/test/unit/node_collection/node_collection_test.rb +23 -0
  272. data/test/unit/node_collection/node_collection_with_indices_test/n.rb +42 -0
  273. data/test/unit/node_collection/node_collection_with_matcher_contexts_test.rb +25 -0
  274. data/test/unit/node_collection/node_collection_with_nodes_test/n.rb +46 -0
  275. data/test/unit/node_collection/node_collection_with_numeric_index_test/n.rb +24 -0
  276. data/test/unit/node_collection/node_collection_with_postdefined_contexts_test/n.rb +22 -0
  277. data/test/unit/node_collection/node_collection_with_predefined_contexts_test/n.rb +23 -0
  278. data/test/unit/node_collection/node_collection_with_string_index_test/n.rb +20 -0
  279. data/test/unit/node_collection/node_collection_with_symbol_index_test/n.rb +20 -0
  280. data/test/unit/node_collection/node_collection_without_indices_test/n.rb +30 -0
  281. data/test/unit/path/path_by_default_test.rb +54 -0
  282. data/test/unit/path/path_test.rb +14 -0
  283. data/test/unit/path/path_with_available_transitions_after_reaching_target_test.rb +40 -0
  284. data/test/unit/path/path_with_available_transitions_test.rb +54 -0
  285. data/test/unit/path/path_with_deep_target_reached_test.rb +50 -0
  286. data/test/unit/path/path_with_deep_target_test.rb +40 -0
  287. data/test/unit/path/path_with_duplicates_test.rb +32 -0
  288. data/test/unit/path/path_with_encountered_transitions_test.rb +34 -0
  289. data/test/unit/path/path_with_guarded_transitions_test.rb +42 -0
  290. data/test/unit/path/path_with_reached_target_test.rb +35 -0
  291. data/test/unit/path/path_with_transitions_test.rb +54 -0
  292. data/test/unit/path/path_with_unreached_target_test.rb +31 -0
  293. data/test/unit/path/path_without_transitions_test.rb +24 -0
  294. data/test/unit/path_collection/path_collection_by_default_test.rb +46 -0
  295. data/test/unit/path_collection/path_collection_test.rb +24 -0
  296. data/test/unit/path_collection/path_collection_with_deep_paths_test.rb +43 -0
  297. data/test/unit/path_collection/path_collection_with_duplicate_nodes_test.rb +31 -0
  298. data/test/unit/path_collection/path_collection_with_from_state_test.rb +27 -0
  299. data/test/unit/path_collection/path_collection_with_paths_test.rb +47 -0
  300. data/test/unit/path_collection/path_collection_with_to_state_test.rb +29 -0
  301. data/test/unit/path_collection/path_with_guarded_paths_test.rb +25 -0
  302. data/test/unit/state/state_after_being_copied_test.rb +19 -0
  303. data/test/unit/state/state_by_default_test.rb +41 -0
  304. data/test/unit/state/state_final_test.rb +28 -0
  305. data/test/unit/state/state_initial_test.rb +13 -0
  306. data/test/unit/state/state_not_final_test.rb +32 -0
  307. data/test/unit/state/state_not_initial_test.rb +13 -0
  308. data/test/unit/state/state_test.rb +44 -0
  309. data/test/unit/state/state_with_cached_lambda_value_test.rb +29 -0
  310. data/test/unit/state/state_with_conflicting_helpers_after_definition_test.rb +38 -0
  311. data/test/unit/state/state_with_conflicting_helpers_before_definition_test.rb +29 -0
  312. data/test/unit/state/state_with_conflicting_machine_name_test.rb +20 -0
  313. data/test/unit/state/state_with_conflicting_machine_test.rb +37 -0
  314. data/test/unit/state/state_with_context_test.rb +60 -0
  315. data/test/unit/state/state_with_dynamic_human_name_test.rb +25 -0
  316. data/test/unit/state/state_with_existing_context_method_test.rb +24 -0
  317. data/test/unit/state/state_with_human_name_test.rb +13 -0
  318. data/test/unit/state/state_with_integer_value_test.rb +32 -0
  319. data/test/unit/state/state_with_invalid_method_call_test.rb +21 -0
  320. data/test/unit/state/state_with_lambda_value_test.rb +37 -0
  321. data/test/unit/state/state_with_matcher_test.rb +18 -0
  322. data/test/unit/state/state_with_multiple_contexts_test.rb +57 -0
  323. data/test/unit/state/state_with_name_test.rb +43 -0
  324. data/test/unit/state/state_with_namespace_test.rb +22 -0
  325. data/test/unit/state/state_with_nil_value_test.rb +35 -0
  326. data/test/unit/state/state_with_redefined_context_method_test.rb +45 -0
  327. data/test/unit/state/state_with_symbolic_value_test.rb +32 -0
  328. data/test/unit/state/state_with_valid_inherited_method_call_for_current_state_test.rb +40 -0
  329. data/test/unit/state/state_with_valid_method_call_for_current_state_test.rb +33 -0
  330. data/test/unit/state/state_with_valid_method_call_for_different_state_test.rb +41 -0
  331. data/test/unit/state/state_without_cached_lambda_value_test.rb +25 -0
  332. data/test/unit/state/state_without_name_test.rb +39 -0
  333. data/test/unit/state_collection/state_collection_by_default_test.rb +21 -0
  334. data/test/unit/state_collection/state_collection_string_test.rb +35 -0
  335. data/test/unit/state_collection/state_collection_test.rb +74 -0
  336. data/test/unit/state_collection/state_collection_with_custom_state_values_test.rb +29 -0
  337. data/test/unit/state_collection/state_collection_with_event_transitions_test.rb +39 -0
  338. data/test/unit/state_collection/state_collection_with_initial_state_test.rb +40 -0
  339. data/test/unit/state_collection/state_collection_with_namespace_test.rb +21 -0
  340. data/test/unit/state_collection/state_collection_with_state_behaviors_test.rb +40 -0
  341. data/test/unit/state_collection/state_collection_with_state_matchers_test.rb +29 -0
  342. data/test/unit/state_collection/state_collection_with_transition_callbacks_test.rb +40 -0
  343. data/test/unit/state_context/state_context_proxy_test.rb +26 -0
  344. data/test/unit/state_context/state_context_proxy_with_if_and_unless_conditions_test.rb +42 -0
  345. data/test/unit/state_context/state_context_proxy_with_if_condition_test.rb +64 -0
  346. data/test/unit/state_context/state_context_proxy_with_multiple_if_conditions_test.rb +32 -0
  347. data/test/unit/state_context/state_context_proxy_with_multiple_unless_conditions_test.rb +32 -0
  348. data/test/unit/state_context/state_context_proxy_with_unless_condition_test.rb +64 -0
  349. data/test/unit/state_context/state_context_proxy_without_conditions_test.rb +31 -0
  350. data/test/unit/state_context/state_context_test.rb +28 -0
  351. data/test/unit/state_context/state_context_transition_test.rb +104 -0
  352. data/test/unit/state_context/state_context_with_matching_transition_test.rb +27 -0
  353. data/test/unit/state_machine/state_machine_by_default_test.rb +12 -0
  354. data/test/unit/state_machine/state_machine_test.rb +20 -0
  355. data/test/unit/transition/transition_after_being_performed_test.rb +48 -0
  356. data/test/unit/transition/transition_after_being_persisted_test.rb +46 -0
  357. data/test/unit/transition/transition_after_being_rolled_back_test.rb +35 -0
  358. data/test/unit/transition/transition_equality_test.rb +52 -0
  359. data/test/unit/transition/transition_loopback_test.rb +18 -0
  360. data/test/unit/transition/transition_test.rb +96 -0
  361. data/test/unit/transition/transition_transient_test.rb +20 -0
  362. data/test/unit/transition/transition_with_action_test.rb +27 -0
  363. data/test/unit/transition/transition_with_after_callbacks_skipped_test.rb +127 -0
  364. data/test/unit/transition/transition_with_after_callbacks_test.rb +93 -0
  365. data/test/unit/transition/transition_with_around_callbacks_test.rb +141 -0
  366. data/test/unit/transition/transition_with_before_callbacks_skipped_test.rb +30 -0
  367. data/test/unit/transition/transition_with_before_callbacks_test.rb +104 -0
  368. data/test/unit/transition/transition_with_custom_machine_attribute_test.rb +28 -0
  369. data/test/unit/transition/transition_with_different_states_test.rb +18 -0
  370. data/test/unit/transition/transition_with_dynamic_to_value_test.rb +19 -0
  371. data/test/unit/transition/transition_with_failure_callbacks_test.rb +84 -0
  372. data/test/unit/transition/transition_with_invalid_nodes_test.rb +29 -0
  373. data/test/unit/transition/transition_with_mixed_callbacks_test.rb +105 -0
  374. data/test/unit/transition/transition_with_multiple_after_callbacks_test.rb +40 -0
  375. data/test/unit/transition/transition_with_multiple_around_callbacks_test.rb +114 -0
  376. data/test/unit/transition/transition_with_multiple_before_callbacks_test.rb +40 -0
  377. data/test/unit/transition/transition_with_multiple_failure_callbacks_test.rb +40 -0
  378. data/test/unit/transition/transition_with_namespace_test.rb +47 -0
  379. data/test/unit/transition/transition_with_perform_arguments_test.rb +35 -0
  380. data/test/unit/transition/transition_with_transactions_test.rb +42 -0
  381. data/test/unit/transition/transition_without_callbacks_test.rb +33 -0
  382. data/test/unit/transition/transition_without_reading_state_test.rb +22 -0
  383. data/test/unit/transition/transition_without_running_action_test.rb +47 -0
  384. data/test/unit/transition_collection/attribute_transition_collection_by_default_test.rb +23 -0
  385. data/test/unit/transition_collection/attribute_transition_collection_marshalling_test.rb +64 -0
  386. data/test/unit/transition_collection/attribute_transition_collection_with_action_error_test.rb +44 -0
  387. data/test/unit/transition_collection/attribute_transition_collection_with_action_failed_test.rb +44 -0
  388. data/test/unit/transition_collection/attribute_transition_collection_with_after_callback_error_test.rb +32 -0
  389. data/test/unit/transition_collection/attribute_transition_collection_with_after_callback_halt_test.rb +33 -0
  390. data/test/unit/transition_collection/attribute_transition_collection_with_around_after_yield_callback_error_test.rb +32 -0
  391. data/test/unit/transition_collection/attribute_transition_collection_with_around_callback_after_yield_error_test.rb +32 -0
  392. data/test/unit/transition_collection/attribute_transition_collection_with_around_callback_after_yield_halt_test.rb +33 -0
  393. data/test/unit/transition_collection/attribute_transition_collection_with_around_callback_before_yield_halt_test.rb +33 -0
  394. data/test/unit/transition_collection/attribute_transition_collection_with_before_callback_error_test.rb +32 -0
  395. data/test/unit/transition_collection/attribute_transition_collection_with_before_callback_halt_test.rb +33 -0
  396. data/test/unit/transition_collection/attribute_transition_collection_with_callbacks_test.rb +68 -0
  397. data/test/unit/transition_collection/attribute_transition_collection_with_event_transitions_test.rb +41 -0
  398. data/test/unit/transition_collection/attribute_transition_collection_with_events_test.rb +44 -0
  399. data/test/unit/transition_collection/attribute_transition_collection_with_skipped_after_callbacks_test.rb +42 -0
  400. data/test/unit/transition_collection/transition_collection_by_default_test.rb +23 -0
  401. data/test/unit/transition_collection/transition_collection_empty_with_block_test.rb +23 -0
  402. data/test/unit/transition_collection/transition_collection_empty_without_block_test.rb +12 -0
  403. data/test/unit/transition_collection/transition_collection_invalid_test.rb +21 -0
  404. data/test/unit/transition_collection/transition_collection_partial_invalid_test.rb +69 -0
  405. data/test/unit/transition_collection/transition_collection_test.rb +26 -0
  406. data/test/unit/transition_collection/transition_collection_valid_test.rb +57 -0
  407. data/test/unit/transition_collection/transition_collection_with_action_error_test.rb +66 -0
  408. data/test/unit/transition_collection/transition_collection_with_action_failed_test.rb +60 -0
  409. data/test/unit/transition_collection/transition_collection_with_action_hook_and_block_test.rb +17 -0
  410. data/test/unit/transition_collection/transition_collection_with_action_hook_and_skipped_action_test.rb +17 -0
  411. data/test/unit/transition_collection/transition_collection_with_action_hook_and_skipped_after_callbacks_test.rb +37 -0
  412. data/test/unit/transition_collection/transition_collection_with_action_hook_base_test.rb +34 -0
  413. data/test/unit/transition_collection/transition_collection_with_action_hook_error_test.rb +29 -0
  414. data/test/unit/transition_collection/transition_collection_with_action_hook_invalid_test.rb +17 -0
  415. data/test/unit/transition_collection/transition_collection_with_action_hook_multiple_test.rb +79 -0
  416. data/test/unit/transition_collection/transition_collection_with_action_hook_test.rb +45 -0
  417. data/test/unit/transition_collection/transition_collection_with_action_hook_with_different_actions_test.rb +48 -0
  418. data/test/unit/transition_collection/transition_collection_with_action_hook_with_nil_action_test.rb +42 -0
  419. data/test/unit/transition_collection/transition_collection_with_after_callback_halt_test.rb +51 -0
  420. data/test/unit/transition_collection/transition_collection_with_before_callback_halt_test.rb +47 -0
  421. data/test/unit/transition_collection/transition_collection_with_block_test.rb +46 -0
  422. data/test/unit/transition_collection/transition_collection_with_callbacks_test.rb +135 -0
  423. data/test/unit/transition_collection/transition_collection_with_different_actions_test.rb +189 -0
  424. data/test/unit/transition_collection/transition_collection_with_duplicate_actions_test.rb +48 -0
  425. data/test/unit/transition_collection/transition_collection_with_empty_actions_test.rb +41 -0
  426. data/test/unit/transition_collection/transition_collection_with_mixed_actions_test.rb +41 -0
  427. data/test/unit/transition_collection/transition_collection_with_skipped_actions_and_block_test.rb +34 -0
  428. data/test/unit/transition_collection/transition_collection_with_skipped_actions_test.rb +69 -0
  429. data/test/unit/transition_collection/transition_collection_with_skipped_after_callbacks_and_around_callbacks_test.rb +53 -0
  430. data/test/unit/transition_collection/transition_collection_with_skipped_after_callbacks_test.rb +34 -0
  431. data/test/unit/transition_collection/transition_collection_with_transactions_test.rb +65 -0
  432. data/test/unit/transition_collection/transition_collection_without_transactions_test.rb +29 -0
  433. metadata +888 -101
  434. data/spec/models/auto_shop_spec.rb +0 -41
  435. data/spec/models/car_spec.rb +0 -90
  436. data/spec/models/motorcycle_spec.rb +0 -44
  437. data/spec/models/traffic_light_spec.rb +0 -56
  438. data/spec/models/vehicle_spec.rb +0 -580
  439. data/spec/spec_helper.rb +0 -7
  440. data/spec/state_machines/assertions_spec.rb +0 -31
  441. data/spec/state_machines/branch_spec.rb +0 -827
  442. data/spec/state_machines/callbacks_spec.rb +0 -706
  443. data/spec/state_machines/errors_spec.rb +0 -1
  444. data/spec/state_machines/event_collection_spec.rb +0 -401
  445. data/spec/state_machines/event_spec.rb +0 -1140
  446. data/spec/state_machines/helper_spec.rb +0 -14
  447. data/spec/state_machines/integration_base_spec.rb +0 -12
  448. data/spec/state_machines/integration_spec.rb +0 -132
  449. data/spec/state_machines/invalid_parallel_transition_spec.rb +0 -18
  450. data/spec/state_machines/invalid_transition_spec.rb +0 -114
  451. data/spec/state_machines/machine_collection_spec.rb +0 -606
  452. data/spec/state_machines/machine_spec.rb +0 -3176
  453. data/spec/state_machines/matcher_helpers_spec.rb +0 -39
  454. data/spec/state_machines/matcher_spec.rb +0 -157
  455. data/spec/state_machines/node_collection_spec.rb +0 -371
  456. data/spec/state_machines/path_collection_spec.rb +0 -271
  457. data/spec/state_machines/path_spec.rb +0 -488
  458. data/spec/state_machines/state_collection_spec.rb +0 -352
  459. data/spec/state_machines/state_context_spec.rb +0 -442
  460. data/spec/state_machines/state_machine_spec.rb +0 -29
  461. data/spec/state_machines/state_spec.rb +0 -970
  462. data/spec/state_machines/transition_collection_spec.rb +0 -2199
  463. data/spec/state_machines/transition_spec.rb +0 -1558
  464. data/spec/support/migration_helpers.rb +0 -59
  465. data/spec/support/models.rb +0 -6
@@ -1,3176 +0,0 @@
1
- describe StateMachines::Machine do
2
- let(:klass) { Class.new }
3
- let(:machine) { StateMachines::Machine.new(klass) }
4
-
5
- let(:object) { klass.new }
6
-
7
- describe 'machine' do
8
- before(:each) do
9
- machine
10
- end
11
- it 'should_have_an_owner_class' do
12
- assert_equal klass, machine.owner_class
13
- end
14
-
15
- it 'should_have_a_name' do
16
- assert_equal :state, machine.name
17
- end
18
-
19
- it 'should_have_an_attribute' do
20
- assert_equal :state, machine.attribute
21
- end
22
-
23
- it 'should_prefix_custom_attributes_with_attribute' do
24
- assert_equal :state_event, machine.attribute(:event)
25
- end
26
-
27
- it 'should_have_an_initial_state' do
28
- assert_not_nil machine.initial_state(object)
29
- end
30
-
31
- it 'should_have_a_nil_initial_state' do
32
- assert_nil machine.initial_state(object).value
33
- end
34
-
35
- it 'should_not_have_any_events' do
36
- assert !machine.events.any?
37
- end
38
-
39
- it 'should_not_have_any_before_callbacks' do
40
- assert machine.callbacks[:before].empty?
41
- end
42
-
43
- it 'should_not_have_any_after_callbacks' do
44
- assert machine.callbacks[:after].empty?
45
- end
46
-
47
- it 'should_not_have_any_failure_callbacks' do
48
- assert machine.callbacks[:failure].empty?
49
- end
50
-
51
- it 'should_not_have_an_action' do
52
- assert_nil machine.action
53
- end
54
-
55
- it 'should_use_tranactions' do
56
- assert_equal true, machine.use_transactions
57
- end
58
-
59
- it 'should_not_have_a_namespace' do
60
- assert_nil machine.namespace
61
- end
62
-
63
- it 'should_have_a_nil_state' do
64
- assert_equal [nil], machine.states.keys
65
- end
66
-
67
- it 'should_set_initial_on_nil_state' do
68
- assert machine.state(nil).initial
69
- end
70
-
71
- it 'should_generate_default_messages' do
72
- assert_equal 'is invalid', machine.generate_message(:invalid)
73
- assert_equal 'cannot transition when parked', machine.generate_message(:invalid_event, [[:state, :parked]])
74
- assert_equal 'cannot transition via "park"', machine.generate_message(:invalid_transition, [[:event, :park]])
75
- end
76
-
77
- it 'should_not_be_extended_by_the_base_integration' do
78
- assert !(
79
- class << machine
80
- ancestors
81
- end).include?(StateMachines::Integrations::Base)
82
- end
83
-
84
-
85
- it 'should_define_a_reader_attribute_for_the_attribute' do
86
- assert object.respond_to?(:state)
87
- end
88
-
89
- it 'should_define_a_writer_attribute_for_the_attribute' do
90
- assert object.respond_to?(:state=)
91
- end
92
-
93
- it 'should_define_a_predicate_for_the_attribute' do
94
- assert object.respond_to?(:state?)
95
- end
96
-
97
- it 'should_define_a_name_reader_for_the_attribute' do
98
- assert object.respond_to?(:state_name)
99
- end
100
-
101
- it 'should_define_an_event_reader_for_the_attribute' do
102
- assert object.respond_to?(:state_events)
103
- end
104
-
105
- it 'should_define_a_transition_reader_for_the_attribute' do
106
- assert object.respond_to?(:state_transitions)
107
- end
108
-
109
- it 'should_define_a_path_reader_for_the_attribute' do
110
- assert object.respond_to?(:state_paths)
111
- end
112
-
113
- it 'should_define_an_event_runner_for_the_attribute' do
114
- assert object.respond_to?(:fire_state_event)
115
- end
116
-
117
- it 'should_not_define_an_event_attribute_reader' do
118
- assert !object.respond_to?(:state_event)
119
- end
120
-
121
- it 'should_not_define_an_event_attribute_writer' do
122
- assert !object.respond_to?(:state_event=)
123
- end
124
-
125
- it 'should_not_define_an_event_transition_attribute_reader' do
126
- assert !object.respond_to?(:state_event_transition)
127
- end
128
-
129
- it 'should_not_define_an_event_transition_attribute_writer' do
130
- assert !object.respond_to?(:state_event_transition=)
131
- end
132
-
133
- it 'should_define_a_human_attribute_name_reader_for_the_attribute' do
134
- assert klass.respond_to?(:human_state_name)
135
- end
136
-
137
- it 'should_define_a_human_event_name_reader_for_the_attribute' do
138
- assert klass.respond_to?(:human_state_event_name)
139
- end
140
-
141
- it 'should_not_define_singular_with_scope' do
142
- assert !klass.respond_to?(:with_state)
143
- end
144
-
145
- it 'should_not_define_singular_without_scope' do
146
- assert !klass.respond_to?(:without_state)
147
- end
148
-
149
- it 'should_not_define_plural_with_scope' do
150
- assert !klass.respond_to?(:with_states)
151
- end
152
-
153
- it 'should_not_define_plural_without_scope' do
154
- assert !klass.respond_to?(:without_states)
155
- end
156
-
157
- it 'should_extend_owner_class_with_class_methods' do
158
- assert((
159
- class << klass
160
- ancestors
161
- end).include?(StateMachines::ClassMethods))
162
- end
163
-
164
- it 'should_include_instance_methods_in_owner_class' do
165
- assert klass.included_modules.include?(StateMachines::InstanceMethods)
166
- end
167
-
168
- it 'should_define_state_machines_reader' do
169
- expected = {state: machine}
170
- assert_equal expected, klass.state_machines
171
- end
172
-
173
- it 'should_raise_exception_if_invalid_option_specified ' do
174
- assert_raise(ArgumentError) { StateMachines::Machine.new(Class.new, invalid: true) }
175
- end
176
-
177
- it 'should_not_raise_exception_if_custom_messages_specified ' do
178
- assert_nothing_raised { StateMachines::Machine.new(Class.new, messages: {invalid_transition: 'Custom'}) }
179
- end
180
-
181
- it 'should_evaluate_a_block_during_initialization ' do
182
- called = true
183
- StateMachines::Machine.new(Class.new) do
184
- called = respond_to?(:event)
185
- end
186
-
187
- assert called
188
- end
189
-
190
- it 'should_provide_matcher_helpers_during_initialization ' do
191
- matchers = []
192
-
193
- StateMachines::Machine.new(Class.new) do
194
- matchers = [all, any, same]
195
- end
196
-
197
- assert_equal [StateMachines::AllMatcher.instance, StateMachines::AllMatcher.instance, StateMachines::LoopbackMatcher.instance], matchers
198
- end
199
-
200
-
201
- end
202
-
203
-
204
- context 'Drawing' do
205
- it 'should raise NotImplementedError' do
206
- machine = StateMachines::Machine.new(Class.new)
207
- expect { machine.draw(:foo) }.to raise_error(NotImplementedError)
208
- end
209
- end
210
-
211
-
212
- context 'WithCustomName' do
213
- let!(:machine) { StateMachines::Machine.new(klass, :status) }
214
- it 'should_use_custom_name' do
215
- assert_equal :status, machine.name
216
- end
217
-
218
- it 'should_use_custom_name_for_attribute' do
219
- assert_equal :status, machine.attribute
220
- end
221
-
222
- it 'should_prefix_custom_attributes_with_custom_name' do
223
- assert_equal :status_event, machine.attribute(:event)
224
- end
225
-
226
- it 'should_define_a_reader_attribute_for_the_attribute' do
227
- assert object.respond_to?(:status)
228
- end
229
-
230
- it 'should_define_a_writer_attribute_for_the_attribute' do
231
- assert object.respond_to?(:status=)
232
- end
233
-
234
- it 'should_define_a_predicate_for_the_attribute' do
235
- assert object.respond_to?(:status?)
236
- end
237
-
238
- it 'should_define_a_name_reader_for_the_attribute' do
239
- assert object.respond_to?(:status_name)
240
- end
241
-
242
- it 'should_define_an_event_reader_for_the_attribute' do
243
- assert object.respond_to?(:status_events)
244
- end
245
-
246
- it 'should_define_a_transition_reader_for_the_attribute' do
247
- assert object.respond_to?(:status_transitions)
248
- end
249
-
250
- it 'should_define_an_event_runner_for_the_attribute' do
251
- assert object.respond_to?(:fire_status_event)
252
- end
253
-
254
- it 'should_define_a_human_attribute_name_reader_for_the_attribute' do
255
- assert klass.respond_to?(:human_status_name)
256
- end
257
-
258
- it 'should_define_a_human_event_name_reader_for_the_attribute' do
259
- assert klass.respond_to?(:human_status_event_name)
260
- end
261
- end
262
-
263
- context 'WithoutInitialization' do
264
- let(:klass) do
265
- Class.new do
266
- def initialize(attributes = {})
267
- attributes.each { |attr, value| send("#{attr}=", value) }
268
- super()
269
- end
270
- end
271
- end
272
-
273
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked, initialize: false) }
274
-
275
- it 'should_not_have_an_initial_state' do
276
- object = klass.new
277
- assert_nil object.state
278
- end
279
-
280
- it 'should_still_allow_manual_initialization' do
281
- klass.send(:include, Module.new do
282
- def initialize(attributes = {})
283
- super()
284
- initialize_state_machines
285
- end
286
- end)
287
-
288
- object = klass.new
289
- assert_equal 'parked', object.state
290
- end
291
- end
292
-
293
- context 'WithStaticInitialState' do
294
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
295
-
296
- it 'should_not_have_dynamic_initial_state' do
297
- assert !machine.dynamic_initial_state?
298
- end
299
-
300
- it 'should_have_an_initial_state' do
301
- object = klass.new
302
- assert_equal 'parked', machine.initial_state(object).value
303
- end
304
-
305
- it 'should_write_to_attribute_when_initializing_state' do
306
- object = klass.allocate
307
- machine.initialize_state(object)
308
- assert_equal 'parked', object.state
309
- end
310
-
311
- it 'should_set_initial_on_state_object' do
312
- assert machine.state(:parked).initial
313
- end
314
-
315
- it 'should_set_initial_state_on_created_object' do
316
- assert_equal 'parked', klass.new.state
317
- end
318
-
319
- it 'not_set_initial_state_even_if_not_empty' do
320
- klass.class_eval do
321
- def initialize(attributes = {})
322
- self.state = 'idling'
323
- super()
324
- end
325
- end
326
- object = klass.new
327
- assert_equal 'idling', object.state
328
- end
329
-
330
- it 'should_set_initial_state_prior_to_initialization' do
331
- base = Class.new do
332
- attr_accessor :state_on_init
333
-
334
- def initialize
335
- self.state_on_init = state
336
- end
337
- end
338
- klass = Class.new(base)
339
- StateMachines::Machine.new(klass, initial: :parked)
340
-
341
- assert_equal 'parked', klass.new.state_on_init
342
- end
343
-
344
- it 'should_be_included_in_known_states' do
345
- assert_equal [:parked], machine.states.keys
346
- end
347
- end
348
-
349
- context 'WithInitialStateWithValueAndOwnerDefault' do
350
- before(:each) do
351
- @original_stderr, $stderr = $stderr, StringIO.new
352
-
353
- end
354
- let(:state_machine_with_defaults) do
355
- Class.new(StateMachines::Machine) do
356
- def owner_class_attribute_default
357
- 0
358
- end
359
- end
360
- end
361
-
362
- it 'should_not_warn_about_wrong_default ' do
363
- state_machine_with_defaults.new(klass, initial: :parked) do
364
- state :parked, value: 0
365
- end
366
- expect($stderr.string).to be_empty
367
- end
368
-
369
- it 'should_warn_about_wrong_default ' do
370
- state_machine_with_defaults.new(klass, initial: :parked) do
371
- state :parked, value: 666
372
- end
373
- expect($stderr.string).to_not be_empty
374
- end
375
-
376
- after(:each) do
377
- $stderr = @original_stderr
378
- end
379
- end
380
-
381
- context 'WithDynamicInitialState ' do
382
- let(:klass) do
383
- Class.new do
384
- attr_accessor :initial_state
385
- end
386
- end
387
-
388
- let!(:machine) do
389
- machine = StateMachines::Machine.new(klass, initial: lambda { |object| object.initial_state || :default })
390
- machine.state :parked, :idling, :default
391
- machine
392
- end
393
-
394
- it 'should_have_dynamic_initial_state ' do
395
- assert machine.dynamic_initial_state?
396
- end
397
-
398
- it 'should_use_the_record_for_determining_the_initial_state ' do
399
- object.initial_state = :parked
400
- assert_equal :parked, machine.initial_state(object).name
401
-
402
- object.initial_state = :idling
403
- assert_equal :idling, machine.initial_state(object).name
404
- end
405
-
406
- it 'should_write_to_attribute_when_initializing_state ' do
407
- object = klass.allocate
408
- object.initial_state = :parked
409
- machine.initialize_state(object)
410
- assert_equal 'parked', object.state
411
- end
412
-
413
- it 'should_set_initial_state_on_created_object ' do
414
- assert_equal 'default', object.state
415
- end
416
-
417
- it 'should_not_set_initial_state_even_if_not_empty ' do
418
- klass.class_eval do
419
- def initialize(attributes = {})
420
- self.state = 'parked'
421
- super()
422
- end
423
- end
424
- object = klass.new
425
- assert_equal 'parked', object.state
426
- end
427
-
428
- it 'should_set_initial_state_after_initialization ' do
429
- base = Class.new do
430
- attr_accessor :state_on_init
431
-
432
- def initialize
433
- self.state_on_init = state
434
- end
435
- end
436
- klass = Class.new(base)
437
- machine = StateMachines::Machine.new(klass, initial: lambda { |object| :parked })
438
- machine.state :parked
439
-
440
- assert_nil klass.new.state_on_init
441
- end
442
-
443
- it 'should_not_be_included_in_known_states ' do
444
- assert_equal [:parked, :idling, :default], machine.states.map { |state| state.name }
445
- end
446
- end
447
-
448
- context 'stateInitialization ' do
449
- let!(:machine) { StateMachines::Machine.new(klass, :state, initial: :parked, initialize: false) }
450
- before(:each) do
451
- object.state = nil
452
- end
453
-
454
- it 'should_set_states_if_nil ' do
455
- machine.initialize_state(object)
456
-
457
- assert_equal 'parked', object.state
458
- end
459
-
460
- it 'should_set_states_if_empty ' do
461
- object.state = ''
462
- machine.initialize_state(object)
463
-
464
- assert_equal 'parked', object.state
465
- end
466
-
467
- it 'should_not_set_states_if_not_empty ' do
468
- object.state = 'idling'
469
- machine.initialize_state(object)
470
-
471
- assert_equal 'idling', object.state
472
- end
473
-
474
- it 'should_set_states_if_not_empty_and_forced ' do
475
- object.state = 'idling'
476
- machine.initialize_state(object, force: true)
477
-
478
- assert_equal 'parked', object.state
479
- end
480
-
481
- it 'should_not_set_state_if_nil_and_nil_is_valid_state ' do
482
- machine.state :initial, value: nil
483
- machine.initialize_state(object)
484
-
485
- assert_nil object.state
486
- end
487
-
488
- it 'should_write_to_hash_if_specified ' do
489
- machine.initialize_state(object, to: hash = {})
490
- assert_equal({'state' => 'parked'}, hash)
491
- end
492
-
493
- it 'should_not_write_to_object_if_writing_to_hash ' do
494
- machine.initialize_state(object, to: {})
495
- assert_nil object.state
496
- end
497
- end
498
-
499
- context 'WithCustomAction' do
500
- let(:machine) { StateMachines::Machine.new(Class.new, action: :save) }
501
-
502
- it 'should_use_the_custom_action ' do
503
- assert_equal :save, machine.action
504
- end
505
- end
506
-
507
- context 'WithNilAction' do
508
- let!(:machine) { StateMachines::Machine.new(Class.new, action: nil, integration: :custom) }
509
- before(:all) do
510
- integration = Module.new do
511
- include StateMachines::Integrations::Base
512
-
513
- @defaults = {action: :save}
514
- end
515
- StateMachines::Integrations.const_set('Custom', integration)
516
- end
517
-
518
- it 'should_have_a_nil_action ' do
519
- assert_nil machine.action
520
- end
521
-
522
- after(:all) do
523
- StateMachines::Integrations.send(:remove_const, 'Custom')
524
- StateMachines::Integrations.send(:reset)
525
- end
526
- end
527
-
528
- context 'WithoutIntegration' do
529
- it ' transaction_should_yield ' do
530
- yielded = false
531
- machine.within_transaction(object) do
532
- yielded = true
533
- end
534
-
535
- assert yielded
536
- end
537
-
538
- it ' invalidation_should_do_nothing ' do
539
- assert_nil machine.invalidate(object, :state, :invalid_transition, [[:event, ' park ']])
540
- end
541
-
542
- it ' reset_should_do_nothing ' do
543
- assert_nil machine.reset(object)
544
- end
545
-
546
- it ' errors_for_should_be_empty ' do
547
- assert_equal '', machine.errors_for(object)
548
- end
549
- end
550
-
551
- context 'WithCustomIntegration' do
552
- before(:each) do
553
- integration = Module.new do
554
- include StateMachines::Integrations::Base
555
-
556
- def self.matching_ancestors
557
- ['Vehicle']
558
- end
559
- end
560
-
561
- StateMachines::Integrations.const_set('Custom', integration)
562
-
563
- superclass = Class.new
564
- self.class.const_set('Vehicle', superclass)
565
-
566
- @klass = Class.new(superclass)
567
- end
568
-
569
- it 'should_be_extended_by_the_integration_if_explicit' do
570
- machine = StateMachines::Machine.new(@klass, :integration => :custom)
571
- assert((class << machine; ancestors; end).include?(StateMachines::Integrations::Custom))
572
- end
573
-
574
- it 'should_not_be_extended_by_the_integration_if_implicit_but_not_available' do
575
- StateMachines::Integrations::Custom.class_eval do
576
- class << self; remove_method :matching_ancestors; end
577
- def self.matching_ancestors
578
- []
579
- end
580
- end
581
-
582
- machine = StateMachines::Machine.new(@klass)
583
- assert(!(class << machine; ancestors; end).include?(StateMachines::Integrations::Custom))
584
- end
585
-
586
- it 'should_not_be_extended_by_the_integration_if_implicit_but_not_matched' do
587
- StateMachines::Integrations::Custom.class_eval do
588
- class << self; remove_method :matching_ancestors; end
589
- def self.matching_ancestors
590
- []
591
- end
592
- end
593
-
594
- machine = StateMachines::Machine.new(@klass)
595
- assert(!(class << machine; ancestors; end).include?(StateMachines::Integrations::Custom))
596
- end
597
-
598
- xit 'should_be_extended_by_the_integration_if_implicit_and_available_and_matches' do
599
- machine = StateMachines::Machine.new(@klass)
600
- assert((class << machine; ancestors; end).include?(StateMachines::Integrations::Custom))
601
- end
602
-
603
- it 'should_not_be_extended_by_the_integration_if_nil' do
604
- machine = StateMachines::Machine.new(@klass, :integration => nil)
605
- assert(!(class << machine; ancestors; end).include?(StateMachines::Integrations::Custom))
606
- end
607
-
608
- it 'should_not_be_extended_by_the_integration_if_false' do
609
- machine = StateMachines::Machine.new(@klass, :integration => false)
610
- assert(!(class << machine; ancestors; end).include?(StateMachines::Integrations::Custom))
611
- end
612
-
613
- after(:each) do
614
- self.class.send(:remove_const, 'Vehicle')
615
- StateMachines::Integrations.send(:remove_const, 'Custom')
616
- StateMachines::Integrations.send(:reset)
617
- end
618
- end
619
-
620
- context 'WithIntegration' do
621
-
622
- before(:each) do
623
- StateMachines::Integrations.const_set('Custom', Module.new do
624
- include StateMachines::Integrations::Base
625
-
626
- @defaults = {action: :save, use_transactions: false}
627
-
628
- attr_reader :initialized, :with_scopes, :without_scopes, :ran_transaction
629
-
630
- def after_initialize
631
- @initialized = true
632
- end
633
-
634
- def create_with_scope(name)
635
- (@with_scopes ||= []) << name
636
- lambda {}
637
- end
638
-
639
- def create_without_scope(name)
640
- (@without_scopes ||= []) << name
641
- lambda {}
642
- end
643
-
644
- def transaction(object)
645
- @ran_transaction = true
646
- yield
647
- end
648
- end)
649
-
650
- end
651
-
652
- let(:machine) { StateMachines::Machine.new(Class.new, integration: :custom) }
653
-
654
- it 'should_call_after_initialize_hook ' do
655
- assert machine.initialized
656
- end
657
-
658
- it 'should_use_the_default_action ' do
659
- assert_equal :save, machine.action
660
- end
661
-
662
- it 'should_use_the_custom_action_if_specified ' do
663
- machine = StateMachines::Machine.new(Class.new, integration: :custom, action: :save!)
664
- assert_equal :save!, machine.action
665
- end
666
-
667
- it 'should_use_the_default_use_transactions ' do
668
- assert_equal false, machine.use_transactions
669
- end
670
-
671
- it 'should_use_the_custom_use_transactions_if_specified ' do
672
- machine = StateMachines::Machine.new(Class.new, integration: :custom, use_transactions: true)
673
- assert_equal true, machine.use_transactions
674
- end
675
-
676
- it 'should_define_a_singular_and_plural_with_scope ' do
677
- assert_equal %w(with_state with_states), machine.with_scopes
678
- end
679
-
680
- it 'should_define_a_singular_and_plural_without_scope ' do
681
- assert_equal %w(without_state without_states), machine.without_scopes
682
- end
683
-
684
- after(:each) do
685
- StateMachines::Integrations.send(:remove_const, 'Custom')
686
- StateMachines::Integrations.send(:reset)
687
- end
688
- end
689
-
690
- context 'WithActionUndefined' do
691
- let!(:machine) { StateMachines::Machine.new(klass, action: :save) }
692
-
693
- it 'should_define_an_event_attribute_reader ' do
694
- assert object.respond_to?(:state_event)
695
- end
696
-
697
- it 'should_define_an_event_attribute_writer ' do
698
- assert object.respond_to?(:state_event=)
699
- end
700
-
701
- it 'should_define_an_event_transition_attribute_reader ' do
702
- assert object.respond_to?(:state_event_transition, true)
703
- end
704
-
705
- it 'should_define_an_event_transition_attribute_writer ' do
706
- assert object.respond_to?(:state_event_transition=, true)
707
- end
708
-
709
- it 'should_not_define_action ' do
710
- assert !object.respond_to?(:save)
711
- end
712
-
713
- it 'should_not_mark_action_hook_as_defined ' do
714
- assert !machine.action_hook?
715
- end
716
- end
717
-
718
- context 'WithActionDefinedInClass' do
719
- let(:klass) do
720
- Class.new do
721
- def save
722
- end
723
- end
724
- end
725
-
726
- let!(:machine) { StateMachines::Machine.new(klass, action: :save) }
727
-
728
- it 'should_define_an_event_attribute_reader ' do
729
- assert object.respond_to?(:state_event)
730
- end
731
-
732
- it 'should_define_an_event_attribute_writer ' do
733
- assert object.respond_to?(:state_event=)
734
- end
735
-
736
- it 'should_define_an_event_transition_attribute_reader ' do
737
- assert object.respond_to?(:state_event_transition, true)
738
- end
739
-
740
- it 'should_define_an_event_transition_attribute_writer ' do
741
- assert object.respond_to?(:state_event_transition=, true)
742
- end
743
-
744
- it 'should_not_define_action ' do
745
- assert !klass.ancestors.any? { |ancestor| ancestor != klass && ancestor.method_defined?(:save) }
746
- end
747
-
748
- it 'should_not_mark_action_hook_as_defined ' do
749
- assert !machine.action_hook?
750
- end
751
- end
752
-
753
- context 'WithActionDefinedInIncludedModule' do
754
- before(:each) do
755
-
756
- @mod = mod = Module.new do
757
- def save
758
- end
759
- end
760
- @klass = Class.new do
761
- include mod
762
- end
763
- @machine = StateMachines::Machine.new(@klass, action: :save)
764
- @object = @klass.new
765
- end
766
-
767
-
768
-
769
- it 'should_define_an_event_attribute_reader ' do
770
- assert @object.respond_to?(:state_event)
771
- end
772
-
773
- it 'should_define_an_event_attribute_writer ' do
774
- assert @object.respond_to?(:state_event=)
775
- end
776
-
777
- it 'should_define_an_event_transition_attribute_reader ' do
778
- assert @object.respond_to?(:state_event_transition, true)
779
- end
780
-
781
- it 'should_define_an_event_transition_attribute_writer ' do
782
- assert @object.respond_to?(:state_event_transition=, true)
783
- end
784
-
785
- it 'should_define_action ' do
786
- assert @klass.ancestors.any? { |ancestor| ![@klass, @mod].include?(ancestor) && ancestor.method_defined?(:save) }
787
- end
788
-
789
- it 'should_keep_action_public ' do
790
- assert @klass.public_method_defined?(:save)
791
- end
792
-
793
- it 'should_mark_action_hook_as_defined ' do
794
- assert @machine.action_hook?
795
- end
796
- end
797
-
798
- context 'WithActionDefinedInSuperclass' do
799
- let(:superclass) do
800
- Class.new do
801
- def save
802
- end
803
- end
804
- end
805
- let(:klass) { Class.new(superclass) }
806
- let!(:machine) { StateMachines::Machine.new(klass, action: :save) }
807
-
808
- it 'should_define_an_event_attribute_reader ' do
809
- assert object.respond_to?(:state_event)
810
- end
811
-
812
- it 'should_define_an_event_attribute_writer ' do
813
- assert object.respond_to?(:state_event=)
814
- end
815
-
816
- it 'should_define_an_event_transition_attribute_reader ' do
817
- assert object.respond_to?(:state_event_transition, true)
818
- end
819
-
820
- it 'should_define_an_event_transition_attribute_writer ' do
821
- assert object.respond_to?(:state_event_transition=, true)
822
- end
823
-
824
- it 'should_define_action ' do
825
- assert klass.ancestors.any? { |ancestor| ![klass, superclass].include?(ancestor) && ancestor.method_defined?(:save) }
826
- end
827
-
828
- it 'should_keep_action_public ' do
829
- assert klass.public_method_defined?(:save)
830
- end
831
-
832
- it 'should_mark_action_hook_as_defined ' do
833
- assert machine.action_hook?
834
- end
835
- end
836
-
837
- context 'WithPrivateAction' do
838
-
839
- let(:superclass) do
840
- Class.new do
841
- private
842
- def save
843
- end
844
- end
845
- end
846
- let(:klass) { Class.new(superclass) }
847
- let!(:machine) { StateMachines::Machine.new(klass, action: :save) }
848
-
849
- it 'should_define_an_event_attribute_reader ' do
850
- assert object.respond_to?(:state_event)
851
- end
852
-
853
- it 'should_define_an_event_attribute_writer ' do
854
- assert object.respond_to?(:state_event=)
855
- end
856
-
857
- it 'should_define_an_event_transition_attribute_reader ' do
858
- assert object.respond_to?(:state_event_transition, true)
859
- end
860
-
861
- it 'should_define_an_event_transition_attribute_writer ' do
862
- assert object.respond_to?(:state_event_transition=, true)
863
- end
864
-
865
- it 'should_define_action ' do
866
- assert klass.ancestors.any? { |ancestor| ![klass, superclass].include?(ancestor) && ancestor.private_method_defined?(:save) }
867
- end
868
-
869
- it 'should_keep_action_private ' do
870
- assert klass.private_method_defined?(:save)
871
- end
872
-
873
- it 'should_mark_action_hook_as_defined ' do
874
- assert machine.action_hook?
875
- end
876
- end
877
-
878
- context 'WithActionAlreadyOverridden' do
879
-
880
- before(:each) do
881
- @superclass = Class.new do
882
- def save
883
- end
884
- end
885
- @klass = Class.new(@superclass)
886
-
887
- StateMachines::Machine.new(@klass, :action => :save)
888
- @machine = StateMachines::Machine.new(@klass, :status, :action => :save)
889
- @object = @klass.new
890
- end
891
-
892
- it 'should_not_redefine_action ' do
893
- assert_equal 1, @klass.ancestors.select { |ancestor| ![@klass, @superclass].include?(ancestor) && ancestor.method_defined?(:save) }.length
894
- end
895
-
896
- it 'should_mark_action_hook_as_defined ' do
897
- assert @machine.action_hook?
898
- end
899
- end
900
-
901
- context 'WithCustomPlural' do
902
-
903
- before(:each) do
904
- @integration = Module.new do
905
- include StateMachines::Integrations::Base
906
-
907
- class << self; attr_accessor :with_scopes, :without_scopes; end
908
- @with_scopes = []
909
- @without_scopes = []
910
-
911
- def create_with_scope(name)
912
- StateMachines::Integrations::Custom.with_scopes << name
913
- lambda {}
914
- end
915
-
916
- def create_without_scope(name)
917
- StateMachines::Integrations::Custom.without_scopes << name
918
- lambda {}
919
- end
920
- end
921
-
922
- StateMachines::Integrations.const_set('Custom', @integration)
923
- end
924
-
925
-
926
- it 'should_define_a_singular_and_plural_with_scope' do
927
- StateMachines::Machine.new(Class.new, :integration => :custom, :plural => 'staties')
928
- assert_equal %w(with_state with_staties), @integration.with_scopes
929
- end
930
-
931
- it 'should_define_a_singular_and_plural_without_scope' do
932
- StateMachines::Machine.new(Class.new, :integration => :custom, :plural => 'staties')
933
- assert_equal %w(without_state without_staties), @integration.without_scopes
934
- end
935
-
936
- it 'should_define_single_with_scope_if_singular_same_as_plural' do
937
- StateMachines::Machine.new(Class.new, :integration => :custom, :plural => 'state')
938
- assert_equal %w(with_state), @integration.with_scopes
939
- end
940
-
941
- it 'should_define_single_without_scope_if_singular_same_as_plural' do
942
- StateMachines::Machine.new(Class.new, :integration => :custom, :plural => 'state')
943
- assert_equal %w(without_state), @integration.without_scopes
944
- end
945
-
946
- after(:each) do
947
- StateMachines::Integrations.send(:remove_const, 'Custom')
948
- StateMachines::Integrations.send(:reset)
949
- end
950
- end
951
-
952
- context 'WithCustomInvalidation' do
953
- let!(:integration) do
954
- integration = Module.new do
955
- include StateMachines::Integrations::Base
956
-
957
- def invalidate(object, attribute, message, values = [])
958
- object.error = generate_message(message, values)
959
- end
960
- end
961
- StateMachines::Integrations.const_set('Custom', integration)
962
- integration
963
- end
964
-
965
- let!(:klass) do
966
- Class.new do
967
- attr_accessor :error
968
- end
969
- end
970
-
971
- let!(:machine) do
972
- machine = StateMachines::Machine.new(klass, integration: :custom, messages: {invalid_transition: 'cannot %s'})
973
- machine.state :parked
974
- machine
975
- end
976
-
977
- before(:each) do
978
-
979
- object.state = 'parked'
980
- end
981
-
982
- it ' generate_custom_message ' do
983
- assert_equal 'cannot park', machine.generate_message(:invalid_transition, [[:event, :park]])
984
- end
985
-
986
- it ' use_custom_message ' do
987
- machine.invalidate(object, :state, :invalid_transition, [[:event, 'park']])
988
- assert_equal 'cannot park', object.error
989
- end
990
-
991
- after(:each) do
992
- StateMachines::Integrations.send(:remove_const, 'Custom')
993
- StateMachines::Integrations.send(:reset)
994
- end
995
- end
996
-
997
- context 'AfterBeingCopied' do
998
- before(:each) do
999
- @machine = StateMachines::Machine.new(Class.new, :state, initial: :parked)
1000
- @machine.event(:ignite) {}
1001
- @machine.before_transition(lambda {})
1002
- @machine.after_transition(lambda {})
1003
- @machine.around_transition(lambda {})
1004
- @machine.after_failure(lambda {})
1005
- @copied_machine = @machine.clone
1006
- end
1007
-
1008
- it 'should_not_have_the_same_collection_of_states ' do
1009
- assert_not_same @copied_machine.states, @machine.states
1010
- end
1011
-
1012
- it 'should_copy_each_state ' do
1013
- assert_not_same @copied_machine.states[:parked], @machine.states[:parked]
1014
- end
1015
-
1016
- it 'should_update_machine_for_each_state ' do
1017
- assert_equal @copied_machine, @copied_machine.states[:parked].machine
1018
- end
1019
-
1020
- it 'should_not_update_machine_for_original_state ' do
1021
- assert_equal @machine, @machine.states[:parked].machine
1022
- end
1023
-
1024
- it 'should_not_have_the_same_collection_of_events ' do
1025
- assert_not_same @copied_machine.events, @machine.events
1026
- end
1027
-
1028
- it 'should_copy_each_event ' do
1029
- assert_not_same @copied_machine.events[:ignite], @machine.events[:ignite]
1030
- end
1031
-
1032
- it 'should_update_machine_for_each_event ' do
1033
- assert_equal @copied_machine, @copied_machine.events[:ignite].machine
1034
- end
1035
-
1036
- it 'should_not_update_machine_for_original_event ' do
1037
- assert_equal @machine, @machine.events[:ignite].machine
1038
- end
1039
-
1040
- it 'should_not_have_the_same_callbacks ' do
1041
- assert_not_same @copied_machine.callbacks, @machine.callbacks
1042
- end
1043
-
1044
- it 'should_not_have_the_same_before_callbacks ' do
1045
- assert_not_same @copied_machine.callbacks[:before], @machine.callbacks[:before]
1046
- end
1047
-
1048
- it 'should_not_have_the_same_after_callbacks ' do
1049
- assert_not_same @copied_machine.callbacks[:after], @machine.callbacks[:after]
1050
- end
1051
-
1052
- it 'should_not_have_the_same_failure_callbacks ' do
1053
- assert_not_same @copied_machine.callbacks[:failure], @machine.callbacks[:failure]
1054
- end
1055
- end
1056
-
1057
- context 'AfterChangingOwnerClass' do
1058
- let(:original_class) { Class.new }
1059
- let(:machine) { StateMachines::Machine.new(original_class) }
1060
- let(:new_class) { Class.new(original_class) }
1061
- let(:new_machine) do
1062
- new_machine = machine.clone
1063
- new_machine.owner_class = new_class
1064
- new_machine
1065
- end
1066
- let(:object) { new_class.new }
1067
-
1068
- it 'should_update_owner_class ' do
1069
- assert_equal new_class, new_machine.owner_class
1070
- end
1071
-
1072
- it 'should_not_change_original_owner_class ' do
1073
- assert_equal original_class, machine.owner_class
1074
- end
1075
-
1076
- it 'should_change_the_associated_machine_in_the_new_class ' do
1077
- assert_equal new_machine, new_class.state_machines[:state]
1078
- end
1079
-
1080
- it 'should_not_change_the_associated_machine_in_the_original_class ' do
1081
- assert_equal machine, original_class.state_machines[:state]
1082
- end
1083
- end
1084
-
1085
- context 'AfterChangingInitialState' do
1086
- let(:machine) do
1087
- machine = StateMachines::Machine.new(klass, initial: :parked)
1088
- machine.initial_state = :idling
1089
- machine
1090
- end
1091
-
1092
- it 'should_change_the_initial_state' do
1093
- assert_equal :idling, machine.initial_state(object).name
1094
- end
1095
-
1096
- it 'should_include_in_known_states' do
1097
- assert_equal [:parked, :idling], machine.states.map { |state| state.name }
1098
- end
1099
-
1100
- it 'should_reset_original_initial_state' do
1101
- assert !machine.state(:parked).initial
1102
- end
1103
-
1104
- it 'should_set_new_state_to_initial' do
1105
- assert machine.state(:idling).initial
1106
- end
1107
- end
1108
-
1109
- context 'WithHelpers' do
1110
- it 'should_throw_exception_with_invalid_scope' do
1111
- assert_raise(RUBY_VERSION < '1.9' ? IndexError : KeyError) { machine.define_helper(:invalid, :park) {} }
1112
- end
1113
- end
1114
-
1115
- context 'WithInstanceHelpers' do
1116
- before(:each) do
1117
- @original_stderr, $stderr = $stderr, StringIO.new
1118
-
1119
- @klass = Class.new
1120
- @machine = StateMachines::Machine.new(@klass)
1121
- @object = @klass.new
1122
- end
1123
-
1124
- it 'should_not_redefine_existing_public_methods' do
1125
- @klass.class_eval do
1126
- def park
1127
- true
1128
- end
1129
- end
1130
-
1131
- @machine.define_helper(:instance, :park) {}
1132
- assert_equal true, @object.park
1133
- end
1134
-
1135
- it 'should_not_redefine_existing_protected_methods' do
1136
- @klass.class_eval do
1137
- protected
1138
- def park
1139
- true
1140
- end
1141
- end
1142
-
1143
- @machine.define_helper(:instance, :park) {}
1144
- assert_equal true, @object.send(:park)
1145
- end
1146
-
1147
- it 'should_not_redefine_existing_private_methods' do
1148
- @klass.class_eval do
1149
- private
1150
- def park
1151
- true
1152
- end
1153
- end
1154
-
1155
- @machine.define_helper(:instance, :park) {}
1156
- assert_equal true, @object.send(:park)
1157
- end
1158
-
1159
- it 'should_warn_if_defined_in_superclass' do
1160
- superclass = Class.new do
1161
- def park
1162
- end
1163
- end
1164
- @klass = Class.new(superclass)
1165
- @machine = StateMachines::Machine.new(@klass)
1166
-
1167
- @machine.define_helper(:instance, :park) {}
1168
- assert_equal "Instance method \"park\" is already defined in #{superclass}, use generic helper instead or set StateMachines::Machine.ignore_method_conflicts = true.\n", $stderr.string
1169
- end
1170
-
1171
- it 'should_warn_if_defined_in_multiple_superclasses' do
1172
- superclass1 = Class.new do
1173
- def park
1174
- end
1175
- end
1176
- superclass2 = Class.new(superclass1) do
1177
- def park
1178
- end
1179
- end
1180
- @klass = Class.new(superclass2)
1181
- @machine = StateMachines::Machine.new(@klass)
1182
-
1183
- @machine.define_helper(:instance, :park) {}
1184
- assert_equal "Instance method \"park\" is already defined in #{superclass1}, use generic helper instead or set StateMachines::Machine.ignore_method_conflicts = true.\n", $stderr.string
1185
- end
1186
-
1187
- it 'should_warn_if_defined_in_module_prior_to_helper_module' do
1188
- mod = Module.new do
1189
- def park
1190
- end
1191
- end
1192
- @klass = Class.new do
1193
- include mod
1194
- end
1195
- @machine = StateMachines::Machine.new(@klass)
1196
-
1197
- @machine.define_helper(:instance, :park) {}
1198
- assert_equal "Instance method \"park\" is already defined in #{mod}, use generic helper instead or set StateMachines::Machine.ignore_method_conflicts = true.\n", $stderr.string
1199
- end
1200
-
1201
- it 'should_not_warn_if_defined_in_module_after_helper_module' do
1202
- klass = Class.new
1203
- StateMachines::Machine.new(klass)
1204
-
1205
- mod = Module.new do
1206
- def park
1207
- end
1208
- end
1209
- @klass.class_eval do
1210
- extend mod
1211
- end
1212
-
1213
- @machine.define_helper(:instance, :park) {}
1214
- assert_equal '', $stderr.string
1215
- end
1216
-
1217
- it 'should_define_if_ignoring_method_conflicts_and_defined_in_superclass' do
1218
-
1219
- StateMachines::Machine.ignore_method_conflicts = true
1220
-
1221
- superclass = Class.new do
1222
- def park
1223
- end
1224
- end
1225
- @klass = Class.new(superclass)
1226
- @machine = StateMachines::Machine.new(@klass)
1227
-
1228
- @machine.define_helper(:instance, :park) { true }
1229
- assert_equal '', $stderr.string
1230
- assert_equal true, @klass.new.park
1231
-
1232
- end
1233
-
1234
- it 'should_define_nonexistent_methods' do
1235
- @machine.define_helper(:instance, :park) { false }
1236
- assert_equal false, @object.park
1237
- end
1238
-
1239
- it 'should_warn_if_defined_multiple_times' do
1240
- @machine.define_helper(:instance, :park) {}
1241
- @machine.define_helper(:instance, :park) {}
1242
-
1243
- assert_equal "Instance method \"park\" is already defined in #{@klass} :state instance helpers, use generic helper instead or set StateMachines::Machine.ignore_method_conflicts = true.\n", $stderr.string
1244
-
1245
- end
1246
-
1247
- it 'should_pass_context_as_arguments' do
1248
- helper_args = nil
1249
- @machine.define_helper(:instance, :park) { |*args| helper_args = args }
1250
- @object.park
1251
- assert_equal 2, helper_args.length
1252
- assert_equal [@machine, @object], helper_args
1253
- end
1254
-
1255
- it 'should_pass_method_arguments_through' do
1256
- helper_args = nil
1257
- @machine.define_helper(:instance, :park) { |*args| helper_args = args }
1258
- @object.park(1, 2, 3)
1259
- assert_equal 5, helper_args.length
1260
- assert_equal [@machine, @object, 1, 2, 3], helper_args
1261
- end
1262
-
1263
- it 'should_allow_string_evaluation' do
1264
- @machine.define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
1265
- def park
1266
- false
1267
- end
1268
- end_eval
1269
- assert_equal false, @object.park
1270
- end
1271
-
1272
-
1273
- after(:each) do
1274
- StateMachines::Machine.ignore_method_conflicts = false
1275
- $stderr = @original_stderr
1276
- end
1277
- end
1278
-
1279
- context 'WithClassHelpers' do
1280
- before(:each) do
1281
- @original_stderr, $stderr = $stderr, StringIO.new
1282
- end
1283
-
1284
- it 'should_not_redefine_existing_public_methods' do
1285
- class << klass
1286
- def states
1287
- []
1288
- end
1289
- end
1290
-
1291
- machine.define_helper(:class, :states) {}
1292
- assert_equal [], klass.states
1293
- end
1294
-
1295
- it 'should_not_redefine_existing_protected_methods' do
1296
- class << klass
1297
- protected
1298
- def states
1299
- []
1300
- end
1301
- end
1302
-
1303
- machine.define_helper(:class, :states) {}
1304
- assert_equal [], klass.send(:states)
1305
- end
1306
-
1307
- it 'should_not_redefine_existing_private_methods' do
1308
- class << klass
1309
- private
1310
- def states
1311
- []
1312
- end
1313
- end
1314
-
1315
- machine.define_helper(:class, :states) {}
1316
- assert_equal [], klass.send(:states)
1317
- end
1318
-
1319
- it 'should_warn_if_defined_in_superclass' do
1320
-
1321
-
1322
-
1323
- superclass = Class.new do
1324
- def self.park
1325
- end
1326
- end
1327
- klass = Class.new(superclass)
1328
- machine = StateMachines::Machine.new(klass)
1329
-
1330
- machine.define_helper(:class, :park) {}
1331
- assert_equal "Class method \"park\" is already defined in #{superclass}, use generic helper instead or set StateMachines::Machine.ignore_method_conflicts = true.\n", $stderr.string
1332
- # ensure
1333
- $stderr = @original_stderr
1334
- end
1335
-
1336
- it 'should_warn_if_defined_in_multiple_superclasses' do
1337
-
1338
- superclass1 = Class.new do
1339
- def self.park
1340
- end
1341
- end
1342
- superclass2 = Class.new(superclass1) do
1343
- def self.park
1344
- end
1345
- end
1346
- klass = Class.new(superclass2)
1347
- machine = StateMachines::Machine.new(klass)
1348
-
1349
- machine.define_helper(:class, :park) {}
1350
- assert_equal "Class method \"park\" is already defined in #{superclass1}, use generic helper instead or set StateMachines::Machine.ignore_method_conflicts = true.\n", $stderr.string
1351
-
1352
- end
1353
-
1354
- it 'should_warn_if_defined_in_module_prior_to_helper_module' do
1355
-
1356
-
1357
-
1358
- mod = Module.new do
1359
- def park
1360
- end
1361
- end
1362
- klass = Class.new do
1363
- extend mod
1364
- end
1365
- machine = StateMachines::Machine.new(klass)
1366
-
1367
- machine.define_helper(:class, :park) {}
1368
- assert_equal "Class method \"park\" is already defined in #{mod}, use generic helper instead or set StateMachines::Machine.ignore_method_conflicts = true.\n", $stderr.string
1369
- # ensure
1370
-
1371
- end
1372
-
1373
-
1374
- it 'should_not_warn_if_defined_in_module_after_helper_module' do
1375
-
1376
-
1377
-
1378
-
1379
- machine = StateMachines::Machine.new(klass)
1380
-
1381
- mod = Module.new do
1382
- def park
1383
- end
1384
- end
1385
- klass.class_eval do
1386
- extend mod
1387
- end
1388
-
1389
- machine.define_helper(:class, :park) {}
1390
- assert_equal '', $stderr.string
1391
- # ensure
1392
- $stderr = @original_stderr
1393
- end
1394
-
1395
- it 'should_define_if_ignoring_method_conflicts_and_defined_in_superclass' do
1396
-
1397
-
1398
- StateMachines::Machine.ignore_method_conflicts = true
1399
-
1400
- superclass = Class.new do
1401
- def self.park
1402
- end
1403
- end
1404
- klass = Class.new(superclass)
1405
- machine = StateMachines::Machine.new(klass)
1406
-
1407
- machine.define_helper(:class, :park) { true }
1408
- assert_equal '', $stderr.string
1409
- assert_equal true, klass.park
1410
- # ensure
1411
- StateMachines::Machine.ignore_method_conflicts = false
1412
- $stderr = @original_stderr
1413
- end
1414
-
1415
- it 'should_define_nonexistent_methods' do
1416
- machine.define_helper(:class, :states) { [] }
1417
- assert_equal [], klass.states
1418
- end
1419
-
1420
- it 'should_warn_if_defined_multiple_times' do
1421
-
1422
-
1423
-
1424
- machine.define_helper(:class, :states) {}
1425
- machine.define_helper(:class, :states) {}
1426
-
1427
- assert_equal "Class method \"states\" is already defined in #{klass} :state class helpers, use generic helper instead or set StateMachines::Machine.ignore_method_conflicts = true.\n", $stderr.string
1428
- # ensure
1429
- $stderr = @original_stderr
1430
- end
1431
-
1432
- it 'should_pass_context_as_arguments' do
1433
- helper_args = nil
1434
- machine.define_helper(:class, :states) { |*args| helper_args = args }
1435
- klass.states
1436
- assert_equal 2, helper_args.length
1437
- assert_equal [machine, klass], helper_args
1438
- end
1439
-
1440
- it 'should_pass_method_arguments_through' do
1441
- helper_args = nil
1442
- machine.define_helper(:class, :states) { |*args| helper_args = args }
1443
- klass.states(1, 2, 3)
1444
- assert_equal 5, helper_args.length
1445
- assert_equal [machine, klass, 1, 2, 3], helper_args
1446
- end
1447
-
1448
- it 'should_allow_string_evaluation' do
1449
- machine.define_helper :class, <<-end_eval, __FILE__, __LINE__ + 1
1450
- def states
1451
- []
1452
- end
1453
- end_eval
1454
- assert_equal [], klass.states
1455
- end
1456
-
1457
- after(:each) do
1458
- $stderr = @original_stderr
1459
- end
1460
- end
1461
-
1462
- context 'WithConflictingHelpersBeforeDefinition' do
1463
-
1464
- before(:each) do
1465
- @original_stderr, $stderr = $stderr, StringIO.new
1466
-
1467
- @superclass = Class.new do
1468
- def self.with_state
1469
- :with_state
1470
- end
1471
-
1472
- def self.with_states
1473
- :with_states
1474
- end
1475
-
1476
- def self.without_state
1477
- :without_state
1478
- end
1479
-
1480
- def self.without_states
1481
- :without_states
1482
- end
1483
-
1484
- def self.human_state_name
1485
- :human_state_name
1486
- end
1487
-
1488
- def self.human_state_event_name
1489
- :human_state_event_name
1490
- end
1491
-
1492
- attr_accessor :status
1493
-
1494
- def state
1495
- 'parked'
1496
- end
1497
-
1498
- def state=(value)
1499
- self.status = value
1500
- end
1501
-
1502
- def state?
1503
- true
1504
- end
1505
-
1506
- def state_name
1507
- :parked
1508
- end
1509
-
1510
- def human_state_name
1511
- 'parked'
1512
- end
1513
-
1514
- def state_events
1515
- [:ignite]
1516
- end
1517
-
1518
- def state_transitions
1519
- [{:parked => :idling}]
1520
- end
1521
-
1522
- def state_paths
1523
- [[{:parked => :idling}]]
1524
- end
1525
-
1526
- def fire_state_event
1527
- true
1528
- end
1529
- end
1530
- @klass = Class.new(@superclass)
1531
-
1532
- StateMachines::Integrations.const_set('Custom', Module.new do
1533
- include StateMachines::Integrations::Base
1534
-
1535
- def create_with_scope(name)
1536
- lambda {|klass, values| []}
1537
- end
1538
-
1539
- def create_without_scope(name)
1540
- lambda {|klass, values| []}
1541
- end
1542
- end)
1543
-
1544
- @machine = StateMachines::Machine.new(@klass, :integration => :custom)
1545
- @machine.state :parked, :idling
1546
- @machine.event :ignite
1547
- @object = @klass.new
1548
- end
1549
-
1550
- it 'should_not_redefine_singular_with_scope' do
1551
- assert_equal :with_state, @klass.with_state
1552
- end
1553
-
1554
- it 'should_not_redefine_plural_with_scope' do
1555
- assert_equal :with_states, @klass.with_states
1556
- end
1557
-
1558
- it 'should_not_redefine_singular_without_scope' do
1559
- assert_equal :without_state, @klass.without_state
1560
- end
1561
-
1562
- it 'should_not_redefine_plural_without_scope' do
1563
- assert_equal :without_states, @klass.without_states
1564
- end
1565
-
1566
- it 'should_not_redefine_human_attribute_name_reader' do
1567
- assert_equal :human_state_name, @klass.human_state_name
1568
- end
1569
-
1570
- it 'should_not_redefine_human_event_name_reader' do
1571
- assert_equal :human_state_event_name, @klass.human_state_event_name
1572
- end
1573
-
1574
- it 'should_not_redefine_attribute_reader' do
1575
- assert_equal 'parked', @object.state
1576
- end
1577
-
1578
- it 'should_not_redefine_attribute_writer' do
1579
- @object.state = 'parked'
1580
- assert_equal 'parked', @object.status
1581
- end
1582
-
1583
- it 'should_not_define_attribute_predicate' do
1584
- assert @object.state?
1585
- end
1586
-
1587
- it 'should_not_redefine_attribute_name_reader' do
1588
- assert_equal :parked, @object.state_name
1589
- end
1590
-
1591
- it 'should_not_redefine_attribute_human_name_reader' do
1592
- assert_equal 'parked', @object.human_state_name
1593
- end
1594
-
1595
- it 'should_not_redefine_attribute_events_reader' do
1596
- assert_equal [:ignite], @object.state_events
1597
- end
1598
-
1599
- it 'should_not_redefine_attribute_transitions_reader' do
1600
- assert_equal [{:parked => :idling}], @object.state_transitions
1601
- end
1602
-
1603
- it 'should_not_redefine_attribute_paths_reader' do
1604
- assert_equal [[{:parked => :idling}]], @object.state_paths
1605
- end
1606
-
1607
- it 'should_not_redefine_event_runner' do
1608
- assert_equal true, @object.fire_state_event
1609
- end
1610
-
1611
- it 'should_output_warning' do
1612
- expected = [
1613
- 'Instance method "state_events"',
1614
- 'Instance method "state_transitions"',
1615
- 'Instance method "fire_state_event"',
1616
- 'Instance method "state_paths"',
1617
- 'Class method "human_state_name"',
1618
- 'Class method "human_state_event_name"',
1619
- 'Instance method "state_name"',
1620
- 'Instance method "human_state_name"',
1621
- 'Class method "with_state"',
1622
- 'Class method "with_states"',
1623
- 'Class method "without_state"',
1624
- 'Class method "without_states"'
1625
- ].map {|method| "#{method} is already defined in #{@superclass.to_s}, use generic helper instead or set StateMachines::Machine.ignore_method_conflicts = true.\n"}.join
1626
-
1627
- assert_equal expected, $stderr.string
1628
- end
1629
-
1630
- after(:each) do
1631
- $stderr = @original_stderr
1632
- StateMachines::Integrations.send(:remove_const, 'Custom')
1633
- StateMachines::Integrations.send(:reset)
1634
- end
1635
-
1636
-
1637
-
1638
- end
1639
-
1640
- context 'WithConflictingHelpersAfterDefinition' do
1641
- let(:klass) do
1642
- Class.new do
1643
- def self.with_state
1644
- :with_state
1645
- end
1646
-
1647
- def self.with_states
1648
- :with_states
1649
- end
1650
-
1651
- def self.without_state
1652
- :without_state
1653
- end
1654
-
1655
- def self.without_states
1656
- :without_states
1657
- end
1658
-
1659
- def self.human_state_name
1660
- :human_state_name
1661
- end
1662
-
1663
- def self.human_state_event_name
1664
- :human_state_event_name
1665
- end
1666
-
1667
- attr_accessor :status
1668
-
1669
- def state
1670
- 'parked'
1671
- end
1672
-
1673
- def state=(value)
1674
- self.status = value
1675
- end
1676
-
1677
- def state?
1678
- true
1679
- end
1680
-
1681
- def state_name
1682
- :parked
1683
- end
1684
-
1685
- def human_state_name
1686
- 'parked'
1687
- end
1688
-
1689
- def state_events
1690
- [:ignite]
1691
- end
1692
-
1693
- def state_transitions
1694
- [{parked: :idling}]
1695
- end
1696
-
1697
- def state_paths
1698
- [[{parked: :idling}]]
1699
- end
1700
-
1701
- def fire_state_event
1702
- true
1703
- end
1704
- end
1705
- end
1706
-
1707
- before(:each) do
1708
-
1709
- @original_stderr, $stderr = $stderr, StringIO.new
1710
-
1711
- StateMachines::Integrations.const_set('Custom', Module.new do
1712
- include StateMachines::Integrations::Base
1713
-
1714
- def create_with_scope(name)
1715
- lambda { |klass, values| [] }
1716
- end
1717
-
1718
- def create_without_scope(name)
1719
- lambda { |klass, values| [] }
1720
- end
1721
- end)
1722
-
1723
- end
1724
-
1725
- after(:each) do
1726
- $stderr = @original_stderr
1727
- end
1728
- let!(:machine) do
1729
- machine = StateMachines::Machine.new(klass, integration: :custom)
1730
- machine.state :parked, :idling
1731
- machine.event :ignite
1732
- machine
1733
- end
1734
-
1735
- it 'should_not_redefine_singular_with_scope' do
1736
- assert_equal :with_state, klass.with_state
1737
- end
1738
-
1739
- it 'should_not_redefine_plural_with_scope' do
1740
- assert_equal :with_states, klass.with_states
1741
- end
1742
-
1743
- it 'should_not_redefine_singular_without_scope' do
1744
- assert_equal :without_state, klass.without_state
1745
- end
1746
-
1747
- it 'should_not_redefine_plural_without_scope' do
1748
- assert_equal :without_states, klass.without_states
1749
- end
1750
-
1751
- it 'should_not_redefine_human_attribute_name_reader' do
1752
- assert_equal :human_state_name, klass.human_state_name
1753
- end
1754
-
1755
- it 'should_not_redefine_human_event_name_reader' do
1756
- assert_equal :human_state_event_name, klass.human_state_event_name
1757
- end
1758
-
1759
- it 'should_not_redefine_attribute_reader' do
1760
- assert_equal 'parked', object.state
1761
- end
1762
-
1763
- it 'should_not_redefine_attribute_writer' do
1764
- object.state = 'parked'
1765
- assert_equal 'parked', object.status
1766
- end
1767
-
1768
- it 'should_not_define_attribute_predicate' do
1769
- assert object.state?
1770
- end
1771
-
1772
- it 'should_not_redefine_attribute_name_reader' do
1773
- assert_equal :parked, object.state_name
1774
- end
1775
-
1776
- it 'should_not_redefine_attribute_human_name_reader' do
1777
- assert_equal 'parked', object.human_state_name
1778
- end
1779
-
1780
- it 'should_not_redefine_attribute_events_reader' do
1781
- assert_equal [:ignite], object.state_events
1782
- end
1783
-
1784
- it 'should_not_redefine_attribute_transitions_reader' do
1785
- assert_equal [{parked: :idling}], object.state_transitions
1786
- end
1787
-
1788
- it 'should_not_redefine_attribute_paths_reader' do
1789
- assert_equal [[{parked: :idling}]], object.state_paths
1790
- end
1791
-
1792
- it 'should_not_redefine_event_runner' do
1793
- assert_equal true, object.fire_state_event
1794
- end
1795
-
1796
- it 'should_allow_super_chaining' do
1797
- klass.class_eval do
1798
- def self.with_state(*states)
1799
- super
1800
- end
1801
-
1802
- def self.with_states(*states)
1803
- super
1804
- end
1805
-
1806
- def self.without_state(*states)
1807
- super
1808
- end
1809
-
1810
- def self.without_states(*states)
1811
- super
1812
- end
1813
-
1814
- def self.human_state_name(state)
1815
- super
1816
- end
1817
-
1818
- def self.human_state_event_name(event)
1819
- super
1820
- end
1821
-
1822
- attr_accessor :status
1823
-
1824
- def state
1825
- super
1826
- end
1827
-
1828
- def state=(value)
1829
- super
1830
- end
1831
-
1832
- def state?(state)
1833
- super
1834
- end
1835
-
1836
- def state_name
1837
- super
1838
- end
1839
-
1840
- def human_state_name
1841
- super
1842
- end
1843
-
1844
- def state_events
1845
- super
1846
- end
1847
-
1848
- def state_transitions
1849
- super
1850
- end
1851
-
1852
- def state_paths
1853
- super
1854
- end
1855
-
1856
- def fire_state_event(event)
1857
- super
1858
- end
1859
- end
1860
-
1861
- assert_equal [], klass.with_state
1862
- assert_equal [], klass.with_states
1863
- assert_equal [], klass.without_state
1864
- assert_equal [], klass.without_states
1865
- assert_equal 'parked', klass.human_state_name(:parked)
1866
- assert_equal 'ignite', klass.human_state_event_name(:ignite)
1867
-
1868
- assert_equal nil, object.state
1869
- object.state = 'idling'
1870
- assert_equal 'idling', object.state
1871
- assert_equal nil, object.status
1872
- assert_equal false, object.state?(:parked)
1873
- assert_equal :idling, object.state_name
1874
- assert_equal 'idling', object.human_state_name
1875
- assert_equal [], object.state_events
1876
- assert_equal [], object.state_transitions
1877
- assert_equal [], object.state_paths
1878
- assert_equal false, object.fire_state_event(:ignite)
1879
- end
1880
-
1881
- it 'should_not_output_warning' do
1882
- assert_equal '', $stderr.string
1883
- end
1884
-
1885
- after(:each) do
1886
- $stderr = @original_stderr
1887
- StateMachines::Integrations.send(:remove_const, 'Custom')
1888
- StateMachines::Integrations.send(:reset)
1889
- end
1890
- end
1891
-
1892
- context 'WithSuperclassConflictingHelpersAfterDefinition' do
1893
- before(:each) do
1894
- @original_stderr, $stderr = $stderr, StringIO.new
1895
-
1896
- @superclass = Class.new
1897
- @klass = Class.new(@superclass)
1898
-
1899
- @machine = StateMachines::Machine.new(@klass)
1900
- @machine.state :parked, :idling
1901
- @machine.event :ignite
1902
-
1903
- @superclass.class_eval do
1904
- def state?
1905
- true
1906
- end
1907
- end
1908
-
1909
- @object = @klass.new
1910
- end
1911
-
1912
-
1913
-
1914
- it 'should_call_superclass_attribute_predicate_without_arguments' do
1915
- expect(@object.state?).to be_truthy
1916
- end
1917
-
1918
- it 'should_define_attribute_predicate_with_arguments' do
1919
- expect(@object.state?(:parked)).to be_falsy
1920
- end
1921
-
1922
- after(:each) do
1923
- $stderr = @original_stderr
1924
- end
1925
- end
1926
-
1927
- context 'WithoutInitialize' do
1928
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
1929
-
1930
- it 'should_initialize_state' do
1931
- assert_equal 'parked', object.state
1932
- end
1933
- end
1934
-
1935
- context 'WithInitializeWithoutSuper' do
1936
- let(:klass) do
1937
- Class.new do
1938
- def initialize
1939
- end
1940
- end
1941
- end
1942
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
1943
-
1944
-
1945
- it 'should_not_initialize_state' do
1946
- assert_nil object.state
1947
- end
1948
- end
1949
-
1950
- context 'WithInitializeAndSuper' do
1951
- let(:klass) do
1952
- Class.new do
1953
- def initialize
1954
- super
1955
- end
1956
- end
1957
- end
1958
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
1959
-
1960
-
1961
- it 'should_initialize_state' do
1962
- assert_equal 'parked', object.state
1963
- end
1964
- end
1965
-
1966
- context 'WithInitializeArgumentsAndBlock' do
1967
- let(:superclass) do
1968
- Class.new do
1969
- attr_reader :args
1970
- attr_reader :block_given
1971
-
1972
- def initialize(*args)
1973
- @args = args
1974
- @block_given = block_given?
1975
- end
1976
- end
1977
- end
1978
-
1979
- let(:klass) { Class.new(superclass) }
1980
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
1981
- let(:object) { klass.new(1, 2, 3) {} }
1982
-
1983
- it 'should_initialize_state' do
1984
- assert_equal 'parked', object.state
1985
- end
1986
-
1987
- it 'should_preserve_arguments' do
1988
- assert_equal [1, 2, 3], object.args
1989
- end
1990
-
1991
- it 'should_preserve_block' do
1992
- assert object.block_given
1993
- end
1994
- end
1995
-
1996
- context 'WithCustomInitialize' do
1997
- let(:klass) do
1998
- Class.new do
1999
- def initialize(state = nil, options = {})
2000
- @state = state
2001
- initialize_state_machines(options)
2002
- end
2003
- end
2004
- end
2005
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2006
-
2007
-
2008
- it 'should_initialize_state' do
2009
- assert_equal 'parked', object.state
2010
- end
2011
-
2012
- it 'should_allow_custom_options' do
2013
- machine.state :idling
2014
- object = klass.new('idling', static: :force)
2015
- assert_equal 'parked', object.state
2016
- end
2017
- end
2018
-
2019
- context 'Persistence' do
2020
- let(:klass) do
2021
- Class.new do
2022
- attr_accessor :state_event
2023
- end
2024
- end
2025
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2026
-
2027
-
2028
- it 'should_allow_reading_state' do
2029
- assert_equal 'parked', machine.read(object, :state)
2030
- end
2031
-
2032
- it 'should_allow_reading_custom_attributes' do
2033
- assert_nil machine.read(object, :event)
2034
-
2035
- object.state_event = 'ignite'
2036
- assert_equal 'ignite', machine.read(object, :event)
2037
- end
2038
-
2039
- it 'should_allow_reading_custom_instance_variables' do
2040
- klass.class_eval do
2041
- attr_writer :state_value
2042
- end
2043
-
2044
- object.state_value = 1
2045
- assert_raise(NoMethodError) { machine.read(object, :value) }
2046
- assert_equal 1, machine.read(object, :value, true)
2047
- end
2048
-
2049
- it 'should_allow_writing_state' do
2050
- machine.write(object, :state, 'idling')
2051
- assert_equal 'idling', object.state
2052
- end
2053
-
2054
- it 'should_allow_writing_custom_attributes' do
2055
- machine.write(object, :event, 'ignite')
2056
- assert_equal 'ignite', object.state_event
2057
- end
2058
-
2059
- it 'should_allow_writing_custom_instance_variables' do
2060
- klass.class_eval do
2061
- attr_reader :state_value
2062
- end
2063
-
2064
- assert_raise(NoMethodError) { machine.write(object, :value, 1) }
2065
- assert_equal 1, machine.write(object, :value, 1, true)
2066
- assert_equal 1, object.state_value
2067
- end
2068
- end
2069
-
2070
- context 'WithStates' do
2071
- before(:each) do
2072
- @parked, @idling = machine.state :parked, :idling
2073
- end
2074
-
2075
- it 'should_have_states' do
2076
- assert_equal [nil, :parked, :idling], machine.states.map { |state| state.name }
2077
- end
2078
-
2079
- it 'should_allow_state_lookup_by_name' do
2080
- assert_equal @parked, machine.states[:parked]
2081
- end
2082
-
2083
- it 'should_allow_state_lookup_by_value' do
2084
- assert_equal @parked, machine.states['parked', :value]
2085
- end
2086
-
2087
- it 'should_allow_human_state_name_lookup' do
2088
- assert_equal 'parked', klass.human_state_name(:parked)
2089
- end
2090
-
2091
- it 'should_raise_exception_on_invalid_human_state_name_lookup' do
2092
- assert_raise(IndexError) { klass.human_state_name(:invalid) }
2093
- # FIXME
2094
- #assert_equal ':invalid is an invalid name', exception.message
2095
- end
2096
-
2097
- it 'should_use_stringified_name_for_value' do
2098
- assert_equal 'parked', @parked.value
2099
- end
2100
-
2101
- it 'should_not_use_custom_matcher' do
2102
- assert_nil @parked.matcher
2103
- end
2104
-
2105
- it 'should_raise_exception_if_invalid_option_specified' do
2106
- assert_raise(ArgumentError) { machine.state(:first_gear, invalid: true) }
2107
- # FIXME
2108
- #assert_equal 'Invalid key(s): invalid', exception.message
2109
- end
2110
-
2111
- it 'should_raise_exception_if_conflicting_type_used_for_name' do
2112
- assert_raise(ArgumentError) { machine.state 'first_gear' }
2113
- # FIXME
2114
- #assert_equal '"first_gear" state defined as String, :parked defined as Symbol; all states must be consistent', exception.message
2115
- end
2116
-
2117
- it 'should_not_raise_exception_if_conflicting_type_is_nil_for_name' do
2118
- assert_nothing_raised { machine.state nil }
2119
- end
2120
- end
2121
-
2122
- context 'WithStatesWithCustomValues' do
2123
- let(:machine) { StateMachines::Machine.new(klass) }
2124
- let(:state) { machine.state :parked, value: 1 }
2125
-
2126
- let(:object) do
2127
- object = klass.new
2128
- object.state = 1
2129
- object
2130
- end
2131
-
2132
- it 'should_use_custom_value' do
2133
- assert_equal 1, state.value
2134
- end
2135
-
2136
- it 'should_allow_lookup_by_custom_value' do
2137
- assert_equal state, machine.states[1, :value]
2138
- end
2139
- end
2140
-
2141
- context 'WithStatesWithCustomHumanNames' do
2142
- let!(:machine) { StateMachines::Machine.new(klass) }
2143
- let!(:state) { machine.state :parked, human_name: 'stopped' }
2144
-
2145
-
2146
- it 'should_use_custom_human_name' do
2147
- assert_equal 'stopped', state.human_name
2148
- end
2149
-
2150
- it 'should_allow_human_state_name_lookup' do
2151
- assert_equal 'stopped', klass.human_state_name(:parked)
2152
- end
2153
- end
2154
-
2155
- context 'WithStatesWithRuntimeDependencies' do
2156
- before(:each) do
2157
- machine.state :parked
2158
- end
2159
-
2160
- it 'should_not_evaluate_value_during_definition' do
2161
- assert_nothing_raised { machine.state :parked, value: lambda { fail ArgumentError } }
2162
- end
2163
-
2164
- it 'should_not_evaluate_if_not_initial_state' do
2165
- machine.state :parked, value: lambda { fail ArgumentError }
2166
- assert_nothing_raised { klass.new }
2167
- end
2168
- end
2169
-
2170
- context 'WithStateWithMatchers' do
2171
- let!(:state) { machine.state :parked, if: lambda { |value| value } }
2172
- before(:each) do
2173
- object.state = 1
2174
- end
2175
-
2176
- it 'should_use_custom_matcher' do
2177
- assert_not_nil state.matcher
2178
- assert state.matches?(1)
2179
- assert !state.matches?(nil)
2180
- end
2181
- end
2182
-
2183
- context 'WithCachedState' do
2184
-
2185
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2186
- let!(:state) { machine.state :parked, value: lambda { Object.new }, cache: true }
2187
-
2188
-
2189
- it 'should_use_evaluated_value' do
2190
- assert_instance_of Object, object.state
2191
- end
2192
-
2193
- it 'use_same_value_across_multiple_objects' do
2194
- assert_equal object.state, klass.new.state
2195
- end
2196
- end
2197
-
2198
- context 'WithStatesWithBehaviors' do
2199
-
2200
- let(:machine) { StateMachines::Machine.new(klass) }
2201
- before(:each) do
2202
- @parked, @idling = machine.state :parked, :idling do
2203
- def speed
2204
- 0
2205
- end
2206
- end
2207
- end
2208
-
2209
- it 'should_define_behaviors_for_each_state' do
2210
- assert_not_nil @parked.context_methods[:speed]
2211
- assert_not_nil @idling.context_methods[:speed]
2212
- end
2213
-
2214
- it 'should_define_different_behaviors_for_each_state' do
2215
- assert_not_equal @parked.context_methods[:speed], @idling.context_methods[:speed]
2216
- end
2217
- end
2218
-
2219
- context 'WithExistingState' do
2220
-
2221
- let!(:state) { machine.state :parked }
2222
- let!(:same_state) { machine.state :parked, value: 1 }
2223
-
2224
- it 'should_not_create_a_new_state' do
2225
- assert_same state, same_state
2226
- end
2227
-
2228
- it 'should_update_attributes' do
2229
- assert_equal 1, state.value
2230
- end
2231
-
2232
- it 'should_no_longer_be_able_to_look_up_state_by_original_value' do
2233
- assert_nil machine.states['parked', :value]
2234
- end
2235
-
2236
- it 'should_be_able_to_look_up_state_by_new_value' do
2237
- assert_equal state, machine.states[1, :value]
2238
- end
2239
- end
2240
-
2241
- context 'WithStateMatchers' do
2242
-
2243
-
2244
- it 'should_empty_array_for_all_matcher' do
2245
- assert_equal [], machine.state(StateMachines::AllMatcher.instance)
2246
- end
2247
-
2248
- it 'should_return_referenced_states_for_blacklist_matcher' do
2249
- assert_instance_of StateMachines::State, machine.state(StateMachines::BlacklistMatcher.new([:parked]))
2250
- end
2251
-
2252
- it 'should_not_allow_configurations' do
2253
- assert_raise(ArgumentError) { machine.state(StateMachines::BlacklistMatcher.new([:parked]), human_name: 'Parked') }
2254
- # FIXME
2255
- #assert_equal 'Cannot configure states when using matchers (using {:human_name=>"Parked"})', exception.message
2256
- end
2257
-
2258
- it 'should_track_referenced_states' do
2259
- machine.state(StateMachines::BlacklistMatcher.new([:parked]))
2260
- assert_equal [nil, :parked], machine.states.map { |state| state.name }
2261
- end
2262
-
2263
- it 'should_eval_context_for_matching_states' do
2264
- contexts_run = []
2265
- machine.event(StateMachines::BlacklistMatcher.new([:parked])) { contexts_run << name }
2266
-
2267
- machine.event :parked
2268
- assert_equal [], contexts_run
2269
-
2270
- machine.event :idling
2271
- assert_equal [:idling], contexts_run
2272
-
2273
- machine.event :first_gear, :second_gear
2274
- assert_equal [:idling, :first_gear, :second_gear], contexts_run
2275
- end
2276
- end
2277
-
2278
- context 'WithOtherStates' do
2279
- let(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2280
- before(:each) do
2281
- @parked, @idling = machine.other_states(:parked, :idling)
2282
- end
2283
-
2284
- it 'should_include_other_states_in_known_states ' do
2285
- assert_equal [@parked, @idling], machine.states.to_a
2286
- end
2287
-
2288
- it 'should_use_default_value ' do
2289
- assert_equal 'idling', @idling.value
2290
- end
2291
-
2292
- it 'should_not_create_matcher ' do
2293
- assert_nil @idling.matcher
2294
- end
2295
- end
2296
-
2297
- context ' WithEvents ' do
2298
-
2299
- it 'should_return_the_created_event ' do
2300
- assert_instance_of StateMachines::Event, machine.event(:ignite)
2301
- end
2302
-
2303
- it 'should_create_event_with_given_name ' do
2304
- event = machine.event(:ignite) {}
2305
- assert_equal :ignite, event.name
2306
- end
2307
-
2308
- it 'should_evaluate_block_within_event_context ' do
2309
- responded = false
2310
- machine.event :ignite do
2311
- responded = respond_to?(:transition)
2312
- end
2313
-
2314
- assert responded
2315
- end
2316
-
2317
- it 'should_be_aliased_as_on ' do
2318
- event = machine.on(:ignite) {}
2319
- assert_equal :ignite, event.name
2320
- end
2321
-
2322
- it 'should_have_events ' do
2323
- event = machine.event(:ignite)
2324
- assert_equal [event], machine.events.to_a
2325
- end
2326
-
2327
- it 'should_allow_human_state_name_lookup ' do
2328
- machine.event(:ignite)
2329
- assert_equal 'ignite', klass.human_state_event_name(:ignite)
2330
- end
2331
-
2332
- it 'should_raise_exception_on_invalid_human_state_event_name_lookup ' do
2333
- machine
2334
- assert_raise(IndexError) { klass.human_state_event_name(:invalid) }
2335
- # FIXME
2336
- #assert_equal ' : invalid is an invalid name ', exception.message
2337
- end
2338
-
2339
- it 'should_raise_exception_if_conflicting_type_used_for_name ' do
2340
- machine.event :park
2341
- assert_raise(ArgumentError) { machine.event 'ignite' }
2342
- # FIXME
2343
- #assert_equal ' "ignite" event defined as String, :park defined as Symbol; all events must be consistent ', exception.message
2344
- end
2345
- end
2346
-
2347
- context ' WithExistingEvent ' do
2348
- let!(:machine) { StateMachines::Machine.new(Class.new) }
2349
- let!(:event) { machine.event(:ignite) }
2350
- let!(:same_event) { machine.event(:ignite) }
2351
-
2352
- it 'should_not_create_new_event ' do
2353
- expect(event).to equal(same_event)
2354
- end
2355
-
2356
- it 'should_allow_accessing_event_without_block ' do
2357
- expect(machine.event(:ignite)).to eq(event)
2358
- end
2359
- end
2360
-
2361
- context ' WithEventsWithCustomHumanNames ' do
2362
- let!(:event) { machine.event(:ignite, human_name: 'start ') }
2363
-
2364
- it 'should_use_custom_human_name ' do
2365
- assert_equal 'start ', event.human_name
2366
- end
2367
-
2368
- it 'should_allow_human_state_name_lookup ' do
2369
- assert_equal 'start ', klass.human_state_event_name(:ignite)
2370
- end
2371
- end
2372
-
2373
- context ' WithEventMatchers ' do
2374
-
2375
-
2376
- it 'should_empty_array_for_all_matcher ' do
2377
- assert_equal [], machine.event(StateMachines::AllMatcher.instance)
2378
- end
2379
-
2380
- it 'should_return_referenced_events_for_blacklist_matcher ' do
2381
- assert_instance_of StateMachines::Event, machine.event(StateMachines::BlacklistMatcher.new([:park]))
2382
- end
2383
-
2384
- it 'should_not_allow_configurations ' do
2385
- assert_raise(ArgumentError) { machine.event(StateMachines::BlacklistMatcher.new([:park]), human_name: ' Park ') }
2386
- # FIXME
2387
- #assert_equal ' Cannot configure events when using matchers (using { :human_name => "Park" }) ', exception.message
2388
- end
2389
-
2390
- it 'should_track_referenced_events ' do
2391
- machine.event(StateMachines::BlacklistMatcher.new([:park]))
2392
- assert_equal [:park], machine.events.map { |event| event.name }
2393
- end
2394
-
2395
- it 'should_eval_context_for_matching_events ' do
2396
- contexts_run = []
2397
- machine.event(StateMachines::BlacklistMatcher.new([:park])) { contexts_run << name }
2398
-
2399
- machine.event :park
2400
- assert_equal [], contexts_run
2401
-
2402
- machine.event :ignite
2403
- assert_equal [:ignite], contexts_run
2404
-
2405
- machine.event :shift_up, :shift_down
2406
- assert_equal [:ignite, :shift_up, :shift_down], contexts_run
2407
- end
2408
- end
2409
-
2410
- context 'WithEventsWithTransitions' do
2411
-
2412
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2413
- let!(:event) do
2414
- machine.event(:ignite) do
2415
- transition parked: :idling
2416
- transition stalled: :idling
2417
- end
2418
- end
2419
-
2420
- it 'should_have_events ' do
2421
- assert_equal [event], machine.events.to_a
2422
- end
2423
-
2424
- it 'should_track_states_defined_in_event_transitions ' do
2425
- assert_equal [:parked, :idling, :stalled], machine.states.map { |state| state.name }
2426
- end
2427
-
2428
- it 'should_not_duplicate_states_defined_in_multiple_event_transitions ' do
2429
- machine.event :park do
2430
- transition idling: :parked
2431
- end
2432
-
2433
- assert_equal [:parked, :idling, :stalled], machine.states.map { |state| state.name }
2434
- end
2435
-
2436
- it 'should_track_state_from_new_events ' do
2437
- machine.event :shift_up do
2438
- transition idling: :first_gear
2439
- end
2440
-
2441
- assert_equal [:parked, :idling, :stalled, :first_gear], machine.states.map { |state| state.name }
2442
- end
2443
- end
2444
-
2445
- context ' WithMultipleEvents ' do
2446
-
2447
- let(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2448
- before(:each) do
2449
- @park, @shift_down = machine.event(:park, :shift_down) do
2450
- transition first_gear: :parked
2451
- end
2452
- end
2453
-
2454
- it 'should_have_events ' do
2455
- assert_equal [@park, @shift_down], machine.events.to_a
2456
- end
2457
-
2458
- it 'should_define_transitions_for_each_event ' do
2459
- [@park, @shift_down].each { |event| assert_equal 1, event.branches.size }
2460
- end
2461
-
2462
- it 'should_transition_the_same_for_each_event ' do
2463
- object = klass.new
2464
- object.state = 'first_gear'
2465
- object.park
2466
- assert_equal 'parked', object.state
2467
-
2468
- object = klass.new
2469
- object.state = 'first_gear'
2470
- object.shift_down
2471
- assert_equal 'parked', object.state
2472
- end
2473
- end
2474
-
2475
- context ' WithTransitions ' do
2476
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2477
-
2478
- it 'should_require_on_event ' do
2479
- assert_raise(ArgumentError) { machine.transition(parked: :idling) }
2480
- # FIXME
2481
- #assert_equal ' Must specify : on event ', exception.message
2482
- end
2483
-
2484
- it 'should_not_allow_except_on_option ' do
2485
- assert_raise(ArgumentError) { machine.transition(except_on: :ignite, on: :ignite) }
2486
- # FIXME
2487
- #assert_equal ' Invalid key(s) : except_on ', exception.message
2488
- end
2489
-
2490
- it 'should_allow_transitioning_without_a_to_state ' do
2491
- assert_nothing_raised { machine.transition(from: :parked, on: :ignite) }
2492
- end
2493
-
2494
- it 'should_allow_transitioning_without_a_from_state ' do
2495
- assert_nothing_raised { machine.transition(to: :idling, on: :ignite) }
2496
- end
2497
-
2498
- it 'should_allow_except_from_option ' do
2499
- assert_nothing_raised { machine.transition(except_from: :idling, on: :ignite) }
2500
- end
2501
-
2502
- it 'should_allow_except_to_option ' do
2503
- assert_nothing_raised { machine.transition(except_to: :parked, on: :ignite) }
2504
- end
2505
-
2506
- it 'should_allow_implicit_options ' do
2507
- branch = machine.transition(first_gear: :second_gear, on: :shift_up)
2508
- assert_instance_of StateMachines::Branch, branch
2509
-
2510
- state_requirements = branch.state_requirements
2511
- assert_equal 1, state_requirements.length
2512
-
2513
- assert_instance_of StateMachines::WhitelistMatcher, state_requirements[0][:from]
2514
- assert_equal [:first_gear], state_requirements[0][:from].values
2515
- assert_instance_of StateMachines::WhitelistMatcher, state_requirements[0][:to]
2516
- assert_equal [:second_gear], state_requirements[0][:to].values
2517
- assert_instance_of StateMachines::WhitelistMatcher, branch.event_requirement
2518
- assert_equal [:shift_up], branch.event_requirement.values
2519
- end
2520
-
2521
- it 'should_allow_multiple_implicit_options ' do
2522
- branch = machine.transition(first_gear: :second_gear, second_gear: :third_gear, on: :shift_up)
2523
-
2524
- state_requirements = branch.state_requirements
2525
- assert_equal 2, state_requirements.length
2526
- end
2527
-
2528
- it 'should_allow_verbose_options ' do
2529
- branch = machine.transition(from: :parked, to: :idling, on: :ignite)
2530
- assert_instance_of StateMachines::Branch, branch
2531
- end
2532
-
2533
- it 'should_include_all_transition_states_in_machine_states ' do
2534
- machine.transition(parked: :idling, on: :ignite)
2535
-
2536
- assert_equal [:parked, :idling], machine.states.map { |state| state.name }
2537
- end
2538
-
2539
- it 'should_include_all_transition_events_in_machine_events ' do
2540
- machine.transition(parked: :idling, on: :ignite)
2541
-
2542
- assert_equal [:ignite], machine.events.map { |event| event.name }
2543
- end
2544
-
2545
- it 'should_allow_multiple_events ' do
2546
- branches = machine.transition(parked: :ignite, on: [:ignite, :shift_up])
2547
-
2548
- assert_equal 2, branches.length
2549
- assert_equal [:ignite, :shift_up], machine.events.map { |event| event.name }
2550
- end
2551
-
2552
- it 'should_not_modify_options ' do
2553
- options = {parked: :idling, on: :ignite}
2554
- machine.transition(options)
2555
-
2556
- assert_equal options, parked: :idling, on: :ignite
2557
- end
2558
- end
2559
-
2560
- context ' WithTransitionCallbacks ' do
2561
-
2562
- let(:klass) do
2563
- Class.new do
2564
- attr_accessor :callbacks
2565
- end
2566
- end
2567
-
2568
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2569
- let!(:event) do
2570
- machine.event :ignite do
2571
- transition parked: :idling
2572
- end
2573
- end
2574
- before(:each) do
2575
- object.callbacks = []
2576
- end
2577
-
2578
- it 'should_not_raise_exception_if_implicit_option_specified ' do
2579
- assert_nothing_raised { machine.before_transition invalid: :valid, do: lambda {} }
2580
- end
2581
-
2582
- it 'should_raise_exception_if_method_not_specified ' do
2583
- assert_raise(ArgumentError) { machine.before_transition to: :idling }
2584
- # FIXME
2585
- #assert_equal ' Method(s) for callback must be specified ', exception.message
2586
- end
2587
-
2588
- it 'should_invoke_callbacks_during_transition' do
2589
- machine.before_transition lambda { |object| object.callbacks << 'before' }
2590
- machine.after_transition lambda { |object| object.callbacks << 'after' }
2591
- machine.around_transition lambda { |object, transition, block| object.callbacks << 'before_around'; block.call; object.callbacks << 'after_around' }
2592
-
2593
- event.fire(object)
2594
- assert_equal %w(before before_around after_around after), object.callbacks
2595
- end
2596
-
2597
- it 'should_allow_multiple_callbacks ' do
2598
- machine.before_transition lambda { |object| object.callbacks << 'before1' }, lambda { |object| object.callbacks << 'before2' }
2599
- machine.after_transition lambda { |object| object.callbacks << 'after1' }, lambda { |object| object.callbacks << 'after2' }
2600
- machine.around_transition(
2601
- lambda { |object, transition, block| object.callbacks << 'before_around1'; block.call; object.callbacks << 'after_around1' },
2602
- lambda { |object, transition, block| object.callbacks << 'before_around2'; block.call; object.callbacks << 'after_around2' }
2603
- )
2604
-
2605
- event.fire(object)
2606
- assert_equal %w(before1 before2 before_around1 before_around2 after_around2 after_around1 after1 after2), object.callbacks
2607
- end
2608
-
2609
- it 'should_allow_multiple_callbacks_with_requirements ' do
2610
- machine.before_transition lambda { |object| object.callbacks << 'before_parked1' }, lambda { |object| object.callbacks << 'before_parked2' }, from: :parked
2611
- machine.before_transition lambda { |object| object.callbacks << 'before_idling1' }, lambda { |object| object.callbacks << 'before_idling2' }, from: :idling
2612
- machine.after_transition lambda { |object| object.callbacks << 'after_parked1' }, lambda { |object| object.callbacks << 'after_parked2' }, from: :parked
2613
- machine.after_transition lambda { |object| object.callbacks << 'after_idling1' }, lambda { |object| object.callbacks << 'after_idling2' }, from: :idling
2614
- machine.around_transition(
2615
- lambda { |object, transition, block| object.callbacks << 'before_around_parked1'; block.call; object.callbacks << 'after_around_parked1' },
2616
- lambda { |object, transition, block| object.callbacks << 'before_around_parked2'; block.call; object.callbacks << 'after_around_parked2' },
2617
- from: :parked
2618
- )
2619
- machine.around_transition(
2620
- lambda { |object, transition, block| object.callbacks << 'before_around_idling1'; block.call; object.callbacks << 'after_around_idling1' },
2621
- lambda { |object, transition, block| object.callbacks << 'before_around_idling2'; block.call; object.callbacks << 'after_around_idling2' },
2622
- from: :idling
2623
- )
2624
-
2625
- event.fire(object)
2626
- assert_equal %w(before_parked1 before_parked2 before_around_parked1 before_around_parked2 after_around_parked2 after_around_parked1 after_parked1 after_parked2), object.callbacks
2627
- end
2628
-
2629
- it 'should_support_from_requirement ' do
2630
- machine.before_transition from: :parked, do: lambda { |object| object.callbacks << :parked }
2631
- machine.before_transition from: :idling, do: lambda { |object| object.callbacks << :idling }
2632
-
2633
- event.fire(object)
2634
- assert_equal [:parked], object.callbacks
2635
- end
2636
-
2637
- it 'should_support_except_from_requirement ' do
2638
- machine.before_transition except_from: :parked, do: lambda { |object| object.callbacks << :parked }
2639
- machine.before_transition except_from: :idling, do: lambda { |object| object.callbacks << :idling }
2640
-
2641
- event.fire(object)
2642
- assert_equal [:idling], object.callbacks
2643
- end
2644
-
2645
- it 'should_support_to_requirement ' do
2646
- machine.before_transition to: :parked, do: lambda { |object| object.callbacks << :parked }
2647
- machine.before_transition to: :idling, do: lambda { |object| object.callbacks << :idling }
2648
-
2649
- event.fire(object)
2650
- assert_equal [:idling], object.callbacks
2651
- end
2652
-
2653
- it 'should_support_except_to_requirement ' do
2654
- machine.before_transition except_to: :parked, do: lambda { |object| object.callbacks << :parked }
2655
- machine.before_transition except_to: :idling, do: lambda { |object| object.callbacks << :idling }
2656
-
2657
- event.fire(object)
2658
- assert_equal [:parked], object.callbacks
2659
- end
2660
-
2661
- it 'should_support_on_requirement ' do
2662
- machine.before_transition on: :park, do: lambda { |object| object.callbacks << :park }
2663
- machine.before_transition on: :ignite, do: lambda { |object| object.callbacks << :ignite }
2664
-
2665
- event.fire(object)
2666
- assert_equal [:ignite], object.callbacks
2667
- end
2668
-
2669
- it 'should_support_except_on_requirement ' do
2670
- machine.before_transition except_on: :park, do: lambda { |object| object.callbacks << :park }
2671
- machine.before_transition except_on: :ignite, do: lambda { |object| object.callbacks << :ignite }
2672
-
2673
- event.fire(object)
2674
- assert_equal [:park], object.callbacks
2675
- end
2676
-
2677
- it 'should_support_implicit_requirement ' do
2678
- machine.before_transition parked: :idling, do: lambda { |object| object.callbacks << :parked }
2679
- machine.before_transition idling: :parked, do: lambda { |object| object.callbacks << :idling }
2680
-
2681
- event.fire(object)
2682
- assert_equal [:parked], object.callbacks
2683
- end
2684
-
2685
- it 'should_track_states_defined_in_transition_callbacks ' do
2686
- machine.before_transition parked: :idling, do: lambda {}
2687
- machine.after_transition first_gear: :second_gear, do: lambda {}
2688
- machine.around_transition third_gear: :fourth_gear, do: lambda {}
2689
-
2690
- assert_equal [:parked, :idling, :first_gear, :second_gear, :third_gear, :fourth_gear], machine.states.map { |state| state.name }
2691
- end
2692
-
2693
- it 'should_not_duplicate_states_defined_in_multiple_event_transitions ' do
2694
- machine.before_transition parked: :idling, do: lambda {}
2695
- machine.after_transition first_gear: :second_gear, do: lambda {}
2696
- machine.after_transition parked: :idling, do: lambda {}
2697
- machine.around_transition parked: :idling, do: lambda {}
2698
-
2699
- assert_equal [:parked, :idling, :first_gear, :second_gear], machine.states.map { |state| state.name }
2700
- end
2701
-
2702
- it 'should_define_predicates_for_each_state ' do
2703
- [:parked?, :idling?].each { |predicate| assert object.respond_to?(predicate) }
2704
- end
2705
- end
2706
-
2707
- context ' WithFailureCallbacks ' do
2708
-
2709
- let!(:klass) do
2710
- Class.new do
2711
- attr_accessor :callbacks
2712
- end
2713
- end
2714
-
2715
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2716
- let!(:event) { machine.event :ignite }
2717
-
2718
- before(:each) do
2719
- object.callbacks = []
2720
- end
2721
-
2722
- it 'should_raise_exception_if_implicit_option_specified ' do
2723
- assert_raise(ArgumentError) { machine.after_failure invalid: :valid, do: lambda {} }
2724
- # FIXME
2725
- #assert_equal 'Invalid key(s) : invalid ', exception.message
2726
- end
2727
-
2728
- it 'should_raise_exception_if_method_not_specified ' do
2729
- assert_raise(ArgumentError) { machine.after_failure on: :ignite }
2730
- # FIXME
2731
- #assert_equal 'Method(s) for callback must be specified ', exception.message
2732
- end
2733
-
2734
- it 'should_invoke_callbacks_during_failed_transition' do
2735
- machine.after_failure lambda { |object| object.callbacks << 'failure' }
2736
-
2737
- event.fire(object)
2738
- assert_equal %w(failure), object.callbacks
2739
- end
2740
-
2741
- it 'should_allow_multiple_callbacks ' do
2742
- machine.after_failure lambda { |object| object.callbacks << 'failure1' }, lambda { |object| object.callbacks << 'failure2' }
2743
-
2744
- event.fire(object)
2745
- assert_equal %w(failure1 failure2), object.callbacks
2746
- end
2747
-
2748
- it 'should_allow_multiple_callbacks_with_requirements ' do
2749
- machine.after_failure lambda { |object| object.callbacks << 'failure_ignite1' }, lambda { |object| object.callbacks << 'failure_ignite2' }, on: :ignite
2750
- machine.after_failure lambda { |object| object.callbacks << 'failure_park1' }, lambda { |object| object.callbacks << 'failure_park2' }, on: :park
2751
-
2752
- event.fire(object)
2753
- assert_equal %w(failure_ignite1 failure_ignite2), object.callbacks
2754
- end
2755
- end
2756
-
2757
- context ' WithPaths ' do
2758
- before(:each) do
2759
- machine.event :ignite do
2760
- transition parked: :idling
2761
- end
2762
- machine.event :shift_up do
2763
- transition first_gear: :second_gear
2764
- end
2765
-
2766
- object.state = 'parked'
2767
- end
2768
-
2769
- it 'should_have_paths ' do
2770
- assert_equal [[StateMachines::Transition.new(object, machine, :ignite, :parked, :idling)]], machine.paths_for(object)
2771
- end
2772
-
2773
- it 'should_allow_requirement_configuration ' do
2774
- assert_equal [[StateMachines::Transition.new(object, machine, :shift_up, :first_gear, :second_gear)]], machine.paths_for(object, from: :first_gear)
2775
- end
2776
- end
2777
-
2778
- context ' WithOwnerSubclass ' do
2779
- before(:each) do
2780
- machine
2781
- end
2782
- let(:subclass) { Class.new(klass) }
2783
-
2784
- it 'should_have_a_different_collection_of_state_machines ' do
2785
- assert_not_same klass.state_machines, subclass.state_machines
2786
- end
2787
-
2788
- it 'should_have_the_same_attribute_associated_state_machines ' do
2789
- assert_equal klass.state_machines, subclass.state_machines
2790
- end
2791
- end
2792
-
2793
- context ' WithExistingMachinesOnOwnerClass ' do
2794
-
2795
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2796
- let!(:second_machine) { StateMachines::Machine.new(klass, :status, initial: :idling) }
2797
-
2798
-
2799
- it 'should_track_each_state_machine ' do
2800
- expected = {state: machine, status: second_machine}
2801
- assert_equal expected, klass.state_machines
2802
- end
2803
-
2804
- it 'should_initialize_state_for_both_machines ' do
2805
- assert_equal 'parked', object.state
2806
- assert_equal 'idling', object.status
2807
- end
2808
- end
2809
-
2810
- context ' WithExistingMachinesWithSameAttributesOnOwnerClass ' do
2811
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2812
- let!(:second_machine) { StateMachines::Machine.new(klass, :public_state, initial: :idling, attribute: :state) }
2813
- let!(:object) { klass.new }
2814
-
2815
- it 'should_track_each_state_machine ' do
2816
- expected = {state: machine, public_state: second_machine}
2817
- assert_equal expected, klass.state_machines
2818
- end
2819
-
2820
- it 'should_write_to_state_only_once ' do
2821
- klass.class_eval do
2822
- attr_reader :write_count
2823
-
2824
- def state=(value)
2825
- @write_count ||= 0
2826
- @write_count += 1
2827
- end
2828
- end
2829
- object = klass.new
2830
-
2831
- assert_equal 1, object.write_count
2832
- end
2833
-
2834
- it 'should_initialize_based_on_first_machine ' do
2835
- assert_equal 'parked', object.state
2836
- end
2837
-
2838
- it 'should_not_allow_second_machine_to_initialize_state ' do
2839
- object.state = nil
2840
- second_machine.initialize_state(object)
2841
- assert_nil object.state
2842
- end
2843
-
2844
- it 'should_allow_transitions_on_both_machines ' do
2845
- machine.event :ignite do
2846
- transition parked: :idling
2847
- end
2848
-
2849
- second_machine.event :park do
2850
- transition idling: :parked
2851
- end
2852
-
2853
- object.ignite
2854
- assert_equal 'idling', object.state
2855
-
2856
- object.park
2857
- assert_equal 'parked', object.state
2858
- end
2859
-
2860
- it 'should_copy_new_states_to_sibling_machines ' do
2861
- first_gear= machine.state :first_gear
2862
- assert_equal first_gear, second_machine.state(:first_gear)
2863
-
2864
- second_gear = second_machine.state :second_gear
2865
- assert_equal second_gear, machine.state(:second_gear)
2866
- end
2867
-
2868
- it 'should_copy_all_existing_states_to_new_machines ' do
2869
- third_machine = StateMachines::Machine.new(klass, :protected_state, attribute: :state)
2870
-
2871
- assert_equal machine.state(:parked), third_machine.state(:parked)
2872
- assert_equal machine.state(:idling), third_machine.state(:idling)
2873
- end
2874
- end
2875
-
2876
- context ' WithExistingMachinesWithSameAttributesOnOwnerSubclass ' do
2877
- let!(:machine) { StateMachines::Machine.new(klass, initial: :parked) }
2878
- let!(:second_machine) { StateMachines::Machine.new(klass, :public_state, initial: :idling, attribute: :state) }
2879
- let(:subclass) { Class.new(klass) }
2880
- let(:object) { subclass.new }
2881
-
2882
- it 'should_not_copy_sibling_machines_to_subclass_after_initialization ' do
2883
- subclass.state_machine(:state) {}
2884
- assert_equal klass.state_machine(:public_state), subclass.state_machine(:public_state)
2885
- end
2886
-
2887
- it 'should_copy_sibling_machines_to_subclass_after_new_state ' do
2888
- subclass_machine = subclass.state_machine(:state) {}
2889
- subclass_machine.state :first_gear
2890
- assert_not_equal klass.state_machine(:public_state), subclass.state_machine(:public_state)
2891
- end
2892
-
2893
- it 'should_copy_new_states_to_sibling_machines ' do
2894
- subclass_machine = subclass.state_machine(:state) {}
2895
- first_gear= subclass_machine.state :first_gear
2896
-
2897
- second_subclass_machine = subclass.state_machine(:public_state)
2898
- assert_equal first_gear, second_subclass_machine.state(:first_gear)
2899
- end
2900
- end
2901
-
2902
- context ' WithNamespace ' do
2903
- let!(:machine) do
2904
- StateMachines::Machine.new(klass, namespace: 'alarm', initial: :active) do
2905
- event :enable do
2906
- transition off: :active
2907
- end
2908
-
2909
- event :disable do
2910
- transition active: :off
2911
- end
2912
- end
2913
- end
2914
-
2915
- it 'should_namespace_state_predicates ' do
2916
- [:alarm_active?, :alarm_off?].each do |name|
2917
- assert object.respond_to?(name)
2918
- end
2919
- end
2920
-
2921
- it 'should_namespace_event_checks ' do
2922
- [:can_enable_alarm?, :can_disable_alarm?].each do |name|
2923
- assert object.respond_to?(name)
2924
- end
2925
- end
2926
-
2927
- it 'should_namespace_event_transition_readers ' do
2928
- [:enable_alarm_transition, :disable_alarm_transition].each do |name|
2929
- assert object.respond_to?(name)
2930
- end
2931
- end
2932
-
2933
- it 'should_namespace_events ' do
2934
- [:enable_alarm, :disable_alarm].each do |name|
2935
- assert object.respond_to?(name)
2936
- end
2937
- end
2938
-
2939
- it 'should_namespace_bang_events ' do
2940
- [:enable_alarm!, :disable_alarm!].each do |name|
2941
- assert object.respond_to?(name)
2942
- end
2943
- end
2944
- end
2945
-
2946
- context ' WithCustomAttribute ' do
2947
-
2948
- let!(:machine) do
2949
- StateMachines::Integrations.const_set('Custom', Module.new do
2950
- include StateMachines::Integrations::Base
2951
-
2952
- @defaults = {action: :save, use_transactions: false}
2953
-
2954
- def create_with_scope(name)
2955
- -> {}
2956
- end
2957
-
2958
- def create_without_scope(name)
2959
- -> {}
2960
- end
2961
- end)
2962
-
2963
- StateMachines::Machine.new(klass, :state, attribute: :state_id, initial: :active, integration: :custom) do
2964
- event :ignite do
2965
- transition parked: :idling
2966
- end
2967
- end
2968
- end
2969
- let(:object) { klass.new }
2970
-
2971
- it 'should_define_a_reader_attribute_for_the_attribute ' do
2972
- assert object.respond_to?(:state_id)
2973
- end
2974
-
2975
- it 'should_define_a_writer_attribute_for_the_attribute ' do
2976
- assert object.respond_to?(:state_id=)
2977
- end
2978
-
2979
- it 'should_define_a_predicate_for_the_attribute ' do
2980
- assert object.respond_to?(:state?)
2981
- end
2982
-
2983
- it 'should_define_a_name_reader_for_the_attribute ' do
2984
- assert object.respond_to?(:state_name)
2985
- end
2986
-
2987
- it 'should_define_a_human_name_reader_for_the_attribute ' do
2988
- assert object.respond_to?(:state_name)
2989
- end
2990
-
2991
- it 'should_define_an_event_reader_for_the_attribute ' do
2992
- assert object.respond_to?(:state_events)
2993
- end
2994
-
2995
- it 'should_define_a_transition_reader_for_the_attribute ' do
2996
- assert object.respond_to?(:state_transitions)
2997
- end
2998
-
2999
- it 'should_define_a_path_reader_for_the_attribute ' do
3000
- assert object.respond_to?(:state_paths)
3001
- end
3002
-
3003
- it 'should_define_an_event_runner_for_the_attribute ' do
3004
- assert object.respond_to?(:fire_state_event)
3005
- end
3006
-
3007
- it 'should_define_a_human_attribute_name_reader ' do
3008
- assert klass.respond_to?(:human_state_name)
3009
- end
3010
-
3011
- it 'should_define_a_human_event_name_reader ' do
3012
- assert klass.respond_to?(:human_state_event_name)
3013
- end
3014
-
3015
- it 'should_define_singular_with_scope ' do
3016
- assert klass.respond_to?(:with_state)
3017
- end
3018
-
3019
- it 'should_define_singular_without_scope ' do
3020
- assert klass.respond_to?(:without_state)
3021
- end
3022
-
3023
- it 'should_define_plural_with_scope ' do
3024
- assert klass.respond_to?(:with_states)
3025
- end
3026
-
3027
- it 'should_define_plural_without_scope ' do
3028
- assert klass.respond_to?(:without_states)
3029
- end
3030
-
3031
- it 'should_define_state_machines_reader ' do
3032
- expected = {state: machine}
3033
- assert_equal expected, klass.state_machines
3034
- end
3035
-
3036
- after(:each) do
3037
- StateMachines::Integrations.send(:remove_const, 'Custom')
3038
- StateMachines::Integrations.send(:reset)
3039
- end
3040
- end
3041
-
3042
- context ' FinderWithoutExistingMachine ' do
3043
- let(:machine) { StateMachines::Machine.find_or_create(klass) }
3044
-
3045
- it 'should_accept_a_block ' do
3046
- called = false
3047
- StateMachines::Machine.find_or_create(Class.new) do
3048
- called = respond_to?(:event)
3049
- end
3050
-
3051
- assert called
3052
- end
3053
-
3054
- it 'should_create_a_new_machine ' do
3055
- assert_not_nil machine
3056
- end
3057
-
3058
- it 'should_use_default_state ' do
3059
- assert_equal :state, machine.attribute
3060
- end
3061
- end
3062
-
3063
- context ' FinderWithExistingOnSameClass ' do
3064
-
3065
- let!(:existing_machine) { StateMachines::Machine.new(klass) }
3066
- let!(:machine) { StateMachines::Machine.find_or_create(klass) }
3067
-
3068
- it 'should_accept_a_block ' do
3069
- called = false
3070
- StateMachines::Machine.find_or_create(klass) do
3071
- called = respond_to?(:event)
3072
- end
3073
-
3074
- assert called
3075
- end
3076
-
3077
- it 'should_not_create_a_new_machine ' do
3078
- assert_same machine, existing_machine
3079
- end
3080
- end
3081
-
3082
- context ' FinderWithExistingMachineOnSuperclass ' do
3083
-
3084
- before(:each) do
3085
- integration = Module.new do
3086
- include StateMachines::Integrations::Base
3087
-
3088
- def self.matches?(klass)
3089
- false
3090
- end
3091
- end
3092
- StateMachines::Integrations.const_set('Custom', integration)
3093
-
3094
- @base_class = Class.new
3095
- @base_machine = StateMachines::Machine.new(@base_class, :status, :action => :save, :integration => :custom)
3096
- @base_machine.event(:ignite) {}
3097
- @base_machine.before_transition(lambda {})
3098
- @base_machine.after_transition(lambda {})
3099
- @base_machine.around_transition(lambda {})
3100
-
3101
- @klass = Class.new(@base_class)
3102
- @machine = StateMachines::Machine.find_or_create(@klass, :status) {}
3103
- end
3104
-
3105
-
3106
- it 'should_accept_a_block' do
3107
- called = false
3108
- StateMachines::Machine.find_or_create(Class.new(@base_class)) do
3109
- called = respond_to?(:event)
3110
- end
3111
-
3112
- assert called
3113
- end
3114
-
3115
- it 'should_not_create_a_new_machine_if_no_block_or_options' do
3116
- machine = StateMachines::Machine.find_or_create(Class.new(@base_class), :status)
3117
-
3118
- assert_same machine, @base_machine
3119
- end
3120
-
3121
- it 'should_create_a_new_machine_if_given_options' do
3122
- machine = StateMachines::Machine.find_or_create(@klass, :status, :initial => :parked)
3123
-
3124
- assert_not_nil machine
3125
- assert_not_same machine, @base_machine
3126
- end
3127
-
3128
- it 'should_create_a_new_machine_if_given_block' do
3129
- assert_not_nil @machine
3130
- assert_not_same @machine, @base_machine
3131
- end
3132
-
3133
- it 'should_copy_the_base_attribute' do
3134
- assert_equal :status, @machine.attribute
3135
- end
3136
-
3137
- it 'should_copy_the_base_configuration' do
3138
- assert_equal :save, @machine.action
3139
- end
3140
-
3141
- it 'should_copy_events' do
3142
- # Can't assert equal arrays since their machines change
3143
- assert_equal 1, @machine.events.length
3144
- end
3145
-
3146
- it 'should_copy_before_callbacks' do
3147
- assert_equal @base_machine.callbacks[:before], @machine.callbacks[:before]
3148
- end
3149
-
3150
- it 'should_copy_after_transitions' do
3151
- assert_equal @base_machine.callbacks[:after], @machine.callbacks[:after]
3152
- end
3153
-
3154
- it 'should_use_the_same_integration' do
3155
- assert((class << @machine; ancestors; end).include?(StateMachines::Integrations::Custom))
3156
- end
3157
-
3158
- after(:each) do
3159
- StateMachines::Integrations.send(:remove_const, 'Custom')
3160
- StateMachines::Integrations.send(:reset)
3161
- end
3162
- end
3163
-
3164
- context 'FinderCustomOptions' do
3165
- let!(:machine) { StateMachines::Machine.find_or_create(klass, :status, initial: :parked) }
3166
-
3167
- it 'should_use_custom_attribute' do
3168
- assert_equal :status, machine.attribute
3169
- end
3170
-
3171
- it 'should_set_custom_initial_state' do
3172
- assert_equal :parked, machine.initial_state(object).name
3173
- end
3174
- end
3175
-
3176
- end