PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/test/unit/event_collection_test.rb

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