PageRenderTime 75ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/test/unit/event_collection_test.rb

https://github.com/johnsonzes/state_machine
Ruby | 358 lines | 274 code | 84 blank | 0 comment | 0 complexity | becbf96b10e73ce48ef3a25a5a46232b MD5 | raw file
  1. require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
  2. class EventCollectionByDefaultTest < Test::Unit::TestCase
  3. def setup
  4. @machine = StateMachine::Machine.new(Class.new)
  5. @events = StateMachine::EventCollection.new(@machine)
  6. end
  7. def test_should_not_have_any_nodes
  8. assert_equal 0, @events.length
  9. end
  10. def test_should_have_a_machine
  11. assert_equal @machine, @events.machine
  12. end
  13. def test_should_not_have_any_valid_events_for_an_object
  14. assert @events.valid_for(@object).empty?
  15. end
  16. def test_should_not_have_any_transitions_for_an_object
  17. assert @events.transitions_for(@object).empty?
  18. end
  19. end
  20. class EventCollectionTest < Test::Unit::TestCase
  21. def setup
  22. machine = StateMachine::Machine.new(Class.new, :namespace => 'alarm')
  23. @events = StateMachine::EventCollection.new(machine)
  24. @events << @open = StateMachine::Event.new(machine, :enable)
  25. machine.events.concat(@events)
  26. end
  27. def test_should_index_by_name
  28. assert_equal @open, @events[:enable, :name]
  29. end
  30. def test_should_index_by_name_by_default
  31. assert_equal @open, @events[:enable]
  32. end
  33. def test_should_index_by_qualified_name
  34. assert_equal @open, @events[:enable_alarm, :qualified_name]
  35. end
  36. end
  37. class EventCollectionWithEventsWithTransitionsTest < Test::Unit::TestCase
  38. def setup
  39. @klass = Class.new
  40. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  41. @events = StateMachine::EventCollection.new(@machine)
  42. @machine.state :idling, :first_gear
  43. @events << @ignite = StateMachine::Event.new(@machine, :ignite)
  44. @ignite.transition :parked => :idling
  45. @events << @park = StateMachine::Event.new(@machine, :park)
  46. @park.transition :idling => :parked
  47. @events << @shift_up = StateMachine::Event.new(@machine, :shift_up)
  48. @shift_up.transition :parked => :first_gear
  49. @shift_up.transition :idling => :first_gear, :if => lambda{false}
  50. @machine.events.concat(@events)
  51. @object = @klass.new
  52. end
  53. def test_should_find_valid_events_based_on_current_state
  54. assert_equal [@ignite, @shift_up], @events.valid_for(@object)
  55. end
  56. def test_should_filter_valid_events_by_from_state
  57. assert_equal [@park], @events.valid_for(@object, :from => :idling)
  58. end
  59. def test_should_filter_valid_events_by_to_state
  60. assert_equal [@shift_up], @events.valid_for(@object, :to => :first_gear)
  61. end
  62. def test_should_filter_valid_events_by_event
  63. assert_equal [@ignite], @events.valid_for(@object, :on => :ignite)
  64. end
  65. def test_should_filter_valid_events_by_multiple_requirements
  66. assert_equal [], @events.valid_for(@object, :from => :idling, :to => :first_gear)
  67. end
  68. def test_should_allow_finding_valid_events_without_guards
  69. assert_equal [@shift_up], @events.valid_for(@object, :from => :idling, :to => :first_gear, :guard => false)
  70. end
  71. def test_should_find_valid_transitions_based_on_current_state
  72. assert_equal [
  73. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
  74. StateMachine::Transition.new(@object, @machine, :shift_up, :parked, :first_gear)
  75. ], @events.transitions_for(@object)
  76. end
  77. def test_should_filter_valid_transitions_by_from_state
  78. assert_equal [StateMachine::Transition.new(@object, @machine, :park, :idling, :parked)], @events.transitions_for(@object, :from => :idling)
  79. end
  80. def test_should_filter_valid_transitions_by_to_state
  81. assert_equal [StateMachine::Transition.new(@object, @machine, :shift_up, :parked, :first_gear)], @events.transitions_for(@object, :to => :first_gear)
  82. end
  83. def test_should_filter_valid_transitions_by_event
  84. assert_equal [StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)], @events.transitions_for(@object, :on => :ignite)
  85. end
  86. def test_should_filter_valid_transitions_by_multiple_requirements
  87. assert_equal [], @events.transitions_for(@object, :from => :idling, :to => :first_gear)
  88. end
  89. def test_should_allow_finding_valid_transitions_without_guards
  90. assert_equal [StateMachine::Transition.new(@object, @machine, :shift_up, :idling, :first_gear)], @events.transitions_for(@object, :from => :idling, :to => :first_gear, :guard => false)
  91. end
  92. end
  93. class EventCollectionWithMultipleEventsTest < Test::Unit::TestCase
  94. def setup
  95. @klass = Class.new
  96. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  97. @events = StateMachine::EventCollection.new(@machine)
  98. @machine.state :first_gear
  99. @machine.event :park, :shift_down
  100. @events << @park = StateMachine::Event.new(@machine, :park)
  101. @park.transition :first_gear => :parked
  102. @events << @shift_down = StateMachine::Event.new(@machine, :shift_down)
  103. @shift_down.transition :first_gear => :parked
  104. @machine.events.concat(@events)
  105. end
  106. def test_should_only_include_all_valid_events_for_an_object
  107. object = @klass.new
  108. object.state = 'first_gear'
  109. assert_equal [@park, @shift_down], @events.valid_for(object)
  110. end
  111. end
  112. class EventCollectionWithoutMachineActionTest < Test::Unit::TestCase
  113. def setup
  114. @klass = Class.new
  115. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  116. @events = StateMachine::EventCollection.new(@machine)
  117. @events << StateMachine::Event.new(@machine, :ignite)
  118. @machine.events.concat(@events)
  119. @object = @klass.new
  120. end
  121. def test_should_not_have_an_attribute_transition
  122. assert_nil @events.attribute_transition_for(@object)
  123. end
  124. end
  125. class EventCollectionAttributeWithMachineActionTest < Test::Unit::TestCase
  126. def setup
  127. @klass = Class.new do
  128. def save
  129. end
  130. end
  131. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  132. @events = StateMachine::EventCollection.new(@machine)
  133. @machine.state :parked, :idling
  134. @events << @ignite = StateMachine::Event.new(@machine, :ignite)
  135. @machine.events.concat(@events)
  136. @object = @klass.new
  137. end
  138. def test_should_not_have_transition_if_nil
  139. @object.state_event = nil
  140. assert_nil @events.attribute_transition_for(@object)
  141. end
  142. def test_should_not_have_transition_if_empty
  143. @object.state_event = ''
  144. assert_nil @events.attribute_transition_for(@object)
  145. end
  146. def test_should_have_invalid_transition_if_invalid_event_specified
  147. @object.state_event = 'invalid'
  148. assert_equal false, @events.attribute_transition_for(@object)
  149. end
  150. def test_should_have_invalid_transition_if_event_cannot_be_fired
  151. @object.state_event = 'ignite'
  152. assert_equal false, @events.attribute_transition_for(@object)
  153. end
  154. def test_should_have_valid_transition_if_event_can_be_fired
  155. @ignite.transition :parked => :idling
  156. @object.state_event = 'ignite'
  157. assert_instance_of StateMachine::Transition, @events.attribute_transition_for(@object)
  158. end
  159. def test_should_have_valid_transition_if_already_defined_in_transition_cache
  160. @ignite.transition :parked => :idling
  161. @object.state_event = nil
  162. @object.send(:state_event_transition=, transition = @ignite.transition_for(@object))
  163. assert_equal transition, @events.attribute_transition_for(@object)
  164. end
  165. def test_should_use_transition_cache_if_both_event_and_transition_are_present
  166. @ignite.transition :parked => :idling
  167. @object.state_event = 'ignite'
  168. @object.send(:state_event_transition=, transition = @ignite.transition_for(@object))
  169. assert_equal transition, @events.attribute_transition_for(@object)
  170. end
  171. end
  172. class EventCollectionAttributeWithNamespacedMachineTest < Test::Unit::TestCase
  173. def setup
  174. @klass = Class.new do
  175. def save
  176. end
  177. end
  178. @machine = StateMachine::Machine.new(@klass, :namespace => 'alarm', :initial => :active, :action => :save)
  179. @events = StateMachine::EventCollection.new(@machine)
  180. @machine.state :active, :off
  181. @events << @disable = StateMachine::Event.new(@machine, :disable)
  182. @machine.events.concat(@events)
  183. @object = @klass.new
  184. end
  185. def test_should_not_have_transition_if_nil
  186. @object.state_event = nil
  187. assert_nil @events.attribute_transition_for(@object)
  188. end
  189. def test_should_have_invalid_transition_if_event_cannot_be_fired
  190. @object.state_event = 'disable'
  191. assert_equal false, @events.attribute_transition_for(@object)
  192. end
  193. def test_should_have_valid_transition_if_event_can_be_fired
  194. @disable.transition :active => :off
  195. @object.state_event = 'disable'
  196. assert_instance_of StateMachine::Transition, @events.attribute_transition_for(@object)
  197. end
  198. end
  199. class EventCollectionWithValidationsTest < Test::Unit::TestCase
  200. def setup
  201. StateMachine::Integrations.const_set('Custom', Module.new do
  202. include StateMachine::Integrations::Base
  203. def invalidate(object, attribute, message, values = [])
  204. (object.errors ||= []) << generate_message(message, values)
  205. end
  206. def reset(object)
  207. object.errors = []
  208. end
  209. end)
  210. @klass = Class.new do
  211. attr_accessor :errors
  212. def initialize
  213. @errors = []
  214. super
  215. end
  216. end
  217. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save, :integration => :custom)
  218. @events = StateMachine::EventCollection.new(@machine)
  219. @parked, @idling = @machine.state :parked, :idling
  220. @events << @ignite = StateMachine::Event.new(@machine, :ignite)
  221. @machine.events.concat(@events)
  222. @object = @klass.new
  223. end
  224. def test_should_invalidate_if_invalid_event_specified
  225. @object.state_event = 'invalid'
  226. @events.attribute_transition_for(@object, true)
  227. assert_equal ['is invalid'], @object.errors
  228. end
  229. def test_should_invalidate_if_event_cannot_be_fired
  230. @object.state = 'idling'
  231. @object.state_event = 'ignite'
  232. @events.attribute_transition_for(@object, true)
  233. assert_equal ['cannot transition when idling'], @object.errors
  234. end
  235. def test_should_invalidate_with_human_name_if_invalid_event_specified
  236. @idling.human_name = 'waiting'
  237. @object.state = 'idling'
  238. @object.state_event = 'ignite'
  239. @events.attribute_transition_for(@object, true)
  240. assert_equal ['cannot transition when waiting'], @object.errors
  241. end
  242. def test_should_not_invalidate_event_can_be_fired
  243. @ignite.transition :parked => :idling
  244. @object.state_event = 'ignite'
  245. @events.attribute_transition_for(@object, true)
  246. assert_equal [], @object.errors
  247. end
  248. def teardown
  249. StateMachine::Integrations.send(:remove_const, 'Custom')
  250. end
  251. end
  252. class EventCollectionWithCustomMachineAttributeTest < Test::Unit::TestCase
  253. def setup
  254. @klass = Class.new do
  255. def save
  256. end
  257. end
  258. @machine = StateMachine::Machine.new(@klass, :state, :attribute => :state_id, :initial => :parked, :action => :save)
  259. @events = StateMachine::EventCollection.new(@machine)
  260. @machine.state :parked, :idling
  261. @events << @ignite = StateMachine::Event.new(@machine, :ignite)
  262. @machine.events.concat(@events)
  263. @object = @klass.new
  264. end
  265. def test_should_not_have_transition_if_nil
  266. @object.state_event = nil
  267. assert_nil @events.attribute_transition_for(@object)
  268. end
  269. def test_should_have_valid_transition_if_event_can_be_fired
  270. @ignite.transition :parked => :idling
  271. @object.state_event = 'ignite'
  272. assert_instance_of StateMachine::Transition, @events.attribute_transition_for(@object)
  273. end
  274. end