state_machines 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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