PageRenderTime 54ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/test/unit/transition_collection_test.rb

https://github.com/amatsuda/state_machine
Ruby | 2098 lines | 1642 code | 456 blank | 0 comment | 3 complexity | ec9ebce36b6c0d5b99b4643481360893 MD5 | raw file
  1. require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
  2. class TransitionCollectionTest < Test::Unit::TestCase
  3. def test_should_raise_exception_if_invalid_option_specified
  4. exception = assert_raise(ArgumentError) {StateMachine::TransitionCollection.new([], :invalid => true)}
  5. end
  6. def test_should_raise_exception_if_multiple_transitions_for_same_attribute_specified
  7. @klass = Class.new
  8. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  9. @machine.state :parked, :idling
  10. @machine.event :ignite
  11. @object = @klass.new
  12. exception = assert_raise(ArgumentError) do
  13. StateMachine::TransitionCollection.new([
  14. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
  15. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  16. ])
  17. end
  18. assert_equal 'Cannot perform multiple transitions in parallel for the same state machine attribute', exception.message
  19. end
  20. end
  21. class TransitionCollectionByDefaultTest < Test::Unit::TestCase
  22. def setup
  23. @transitions = StateMachine::TransitionCollection.new
  24. end
  25. def test_should_not_skip_actions
  26. assert !@transitions.skip_actions
  27. end
  28. def test_should_not_skip_after
  29. assert !@transitions.skip_after
  30. end
  31. def test_should_use_transaction
  32. assert @transitions.use_transaction
  33. end
  34. def test_should_be_empty
  35. assert @transitions.empty?
  36. end
  37. end
  38. class TransitionCollectionEmptyWithoutBlockTest < Test::Unit::TestCase
  39. def setup
  40. @transitions = StateMachine::TransitionCollection.new
  41. @result = @transitions.perform
  42. end
  43. def test_should_succeed
  44. assert_equal true, @result
  45. end
  46. end
  47. class TransitionCollectionEmptyWithBlockTest < Test::Unit::TestCase
  48. def setup
  49. @transitions = StateMachine::TransitionCollection.new
  50. end
  51. def test_should_raise_exception_if_perform_raises_exception
  52. assert_raise(ArgumentError) { @transitions.perform { raise ArgumentError } }
  53. end
  54. def test_should_use_block_result_if_non_boolean
  55. assert_equal 1, @transitions.perform { 1 }
  56. end
  57. def test_should_use_block_result_if_false
  58. assert_equal false, @transitions.perform { false }
  59. end
  60. def test_should_use_block_reslut_if_nil
  61. assert_equal nil, @transitions.perform { nil }
  62. end
  63. end
  64. class TransitionCollectionInvalidTest < Test::Unit::TestCase
  65. def setup
  66. @transitions = StateMachine::TransitionCollection.new([false])
  67. end
  68. def test_should_be_empty
  69. assert @transitions.empty?
  70. end
  71. def test_should_not_succeed
  72. assert_equal false, @transitions.perform
  73. end
  74. def test_should_not_run_perform_block
  75. ran_block = false
  76. @transitions.perform { ran_block = true }
  77. assert !ran_block
  78. end
  79. end
  80. class TransitionCollectionPartialInvalidTest < Test::Unit::TestCase
  81. def setup
  82. @klass = Class.new do
  83. attr_accessor :ran_transaction
  84. end
  85. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  86. @machine.state :idling
  87. @machine.event :ignite
  88. @machine.before_transition {@ran_before = true}
  89. @machine.after_transition {@ran_after = true}
  90. @machine.around_transition {|block| @ran_around_before = true; block.call; @ran_around_after = true}
  91. class << @machine
  92. def within_transaction(object)
  93. object.ran_transaction = true
  94. end
  95. end
  96. @object = @klass.new
  97. @transitions = StateMachine::TransitionCollection.new([
  98. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling),
  99. false
  100. ])
  101. end
  102. def test_should_not_store_invalid_values
  103. assert_equal 1, @transitions.length
  104. end
  105. def test_should_not_succeed
  106. assert_equal false, @transitions.perform
  107. end
  108. def test_should_not_start_transaction
  109. assert !@object.ran_transaction
  110. end
  111. def test_should_not_run_perform_block
  112. ran_block = false
  113. @transitions.perform { ran_block = true }
  114. assert !ran_block
  115. end
  116. def test_should_not_run_before_callbacks
  117. assert !@ran_before
  118. end
  119. def test_should_not_persist_states
  120. assert_equal 'parked', @object.state
  121. end
  122. def test_should_not_run_after_callbacks
  123. assert !@ran_after
  124. end
  125. def test_should_not_run_around_callbacks_before_yield
  126. assert !@ran_around_before
  127. end
  128. def test_should_not_run_around_callbacks_after_yield
  129. assert !@ran_around_after
  130. end
  131. end
  132. class TransitionCollectionValidTest < Test::Unit::TestCase
  133. def setup
  134. @klass = Class.new do
  135. attr_reader :persisted
  136. def initialize
  137. super
  138. @persisted = []
  139. end
  140. def state=(value)
  141. @persisted << 'state' if @persisted
  142. @state = value
  143. end
  144. def status=(value)
  145. @persisted << 'status' if @persisted
  146. @status = value
  147. end
  148. end
  149. @state = StateMachine::Machine.new(@klass, :initial => :parked)
  150. @state.state :idling
  151. @state.event :ignite
  152. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
  153. @status.state :second_gear
  154. @status.event :shift_up
  155. @object = @klass.new
  156. @result = StateMachine::TransitionCollection.new([
  157. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  158. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  159. ]).perform
  160. end
  161. def test_should_succeed
  162. assert_equal true, @result
  163. end
  164. def test_should_persist_each_state
  165. assert_equal 'idling', @object.state
  166. assert_equal 'second_gear', @object.status
  167. end
  168. def test_should_persist_in_order
  169. assert_equal ['state', 'status'], @object.persisted
  170. end
  171. def test_should_store_results_in_transitions
  172. assert_nil @state_transition.result
  173. assert_nil @status_transition.result
  174. end
  175. end
  176. class TransitionCollectionWithoutTransactionsTest < Test::Unit::TestCase
  177. def setup
  178. @klass = Class.new do
  179. attr_accessor :ran_transaction
  180. end
  181. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  182. @machine.state :idling
  183. @machine.event :ignite
  184. class << @machine
  185. def within_transaction(object)
  186. object.ran_transaction = true
  187. end
  188. end
  189. @object = @klass.new
  190. @transitions = StateMachine::TransitionCollection.new([
  191. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  192. ], :transaction => false)
  193. @transitions.perform
  194. end
  195. def test_should_not_run_within_transaction
  196. assert !@object.ran_transaction
  197. end
  198. end
  199. class TransitionCollectionWithTransactionsTest < Test::Unit::TestCase
  200. def setup
  201. @klass = Class.new do
  202. attr_accessor :running_transaction, :cancelled_transaction
  203. end
  204. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  205. @machine.state :idling
  206. @machine.event :ignite
  207. class << @machine
  208. def within_transaction(object)
  209. object.running_transaction = true
  210. object.cancelled_transaction = yield == false
  211. object.running_transaction = false
  212. end
  213. end
  214. @object = @klass.new
  215. @transitions = StateMachine::TransitionCollection.new([
  216. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  217. ], :transaction => true)
  218. end
  219. def test_should_run_before_callbacks_within_transaction
  220. @machine.before_transition {|object| @in_transaction = object.running_transaction}
  221. @transitions.perform
  222. assert @in_transaction
  223. end
  224. def test_should_run_action_within_transaction
  225. @transitions.perform { @in_transaction = @object.running_transaction }
  226. assert @in_transaction
  227. end
  228. def test_should_run_after_callbacks_within_transaction
  229. @machine.after_transition {|object| @in_transaction = object.running_transaction}
  230. @transitions.perform
  231. assert @in_transaction
  232. end
  233. def test_should_cancel_the_transaction_on_before_halt
  234. @machine.before_transition {throw :halt}
  235. @transitions.perform
  236. assert @object.cancelled_transaction
  237. end
  238. def test_should_cancel_the_transaction_on_action_failure
  239. @transitions.perform { false }
  240. assert @object.cancelled_transaction
  241. end
  242. def test_should_not_cancel_the_transaction_on_after_halt
  243. @machine.after_transition {throw :halt}
  244. @transitions.perform
  245. assert !@object.cancelled_transaction
  246. end
  247. end
  248. class TransitionCollectionWithEmptyActionsTest < Test::Unit::TestCase
  249. def setup
  250. @klass = Class.new
  251. @state = StateMachine::Machine.new(@klass, :initial => :parked)
  252. @state.state :idling
  253. @state.event :ignite
  254. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
  255. @status.state :second_gear
  256. @status.event :shift_up
  257. @object = @klass.new
  258. @transitions = StateMachine::TransitionCollection.new([
  259. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  260. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  261. ])
  262. @object.state = 'idling'
  263. @object.status = 'second_gear'
  264. @result = @transitions.perform
  265. end
  266. def test_should_succeed
  267. assert_equal true, @result
  268. end
  269. def test_should_persist_states
  270. assert_equal 'idling', @object.state
  271. assert_equal 'second_gear', @object.status
  272. end
  273. def test_should_store_results_in_transitions
  274. assert_nil @state_transition.result
  275. assert_nil @status_transition.result
  276. end
  277. end
  278. class TransitionCollectionWithSkippedActionsTest < Test::Unit::TestCase
  279. def setup
  280. @klass = Class.new do
  281. attr_reader :actions
  282. def save_state
  283. (@actions ||= []) << :save_state
  284. :save_state
  285. end
  286. def save_status
  287. (@actions ||= []) << :save_status
  288. :save_status
  289. end
  290. end
  291. @callbacks = []
  292. @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save_state)
  293. @state.state :idling
  294. @state.event :ignite
  295. @state.before_transition {@callbacks << :state_before}
  296. @state.after_transition {@callbacks << :state_after}
  297. @state.around_transition {|block| @callbacks << :state_around_before; block.call; @callbacks << :state_around_after}
  298. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save_status)
  299. @status.state :second_gear
  300. @status.event :shift_up
  301. @status.before_transition {@callbacks << :status_before}
  302. @status.after_transition {@callbacks << :status_after}
  303. @status.around_transition {|block| @callbacks << :status_around_before; block.call; @callbacks << :status_around_after}
  304. @object = @klass.new
  305. @transitions = StateMachine::TransitionCollection.new([
  306. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  307. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  308. ], :actions => false)
  309. @result = @transitions.perform
  310. end
  311. def test_should_skip_actions
  312. assert_equal true, @transitions.skip_actions
  313. end
  314. def test_should_succeed
  315. assert_equal true, @result
  316. end
  317. def test_should_persist_states
  318. assert_equal 'idling', @object.state
  319. assert_equal 'second_gear', @object.status
  320. end
  321. def test_should_not_run_actions
  322. assert_nil @object.actions
  323. end
  324. def test_should_store_results_in_transitions
  325. assert_nil @state_transition.result
  326. assert_nil @status_transition.result
  327. end
  328. def test_should_run_all_callbacks
  329. assert_equal [:state_before, :state_around_before, :status_before, :status_around_before, :status_around_after, :status_after, :state_around_after, :state_after], @callbacks
  330. end
  331. end
  332. class TransitionCollectionWithSkippedActionsAndBlockTest < Test::Unit::TestCase
  333. def setup
  334. @klass = Class.new
  335. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save_state)
  336. @machine.state :idling
  337. @machine.event :ignite
  338. @object = @klass.new
  339. @transitions = StateMachine::TransitionCollection.new([
  340. @state_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  341. ], :actions => false)
  342. @result = @transitions.perform { @ran_block = true; 1 }
  343. end
  344. def test_should_succeed
  345. assert_equal 1, @result
  346. end
  347. def test_should_persist_states
  348. assert_equal 'idling', @object.state
  349. end
  350. def test_should_run_block
  351. assert @ran_block
  352. end
  353. def test_should_store_results_in_transitions
  354. assert_equal 1, @state_transition.result
  355. end
  356. end
  357. class TransitionCollectionWithDuplicateActionsTest < Test::Unit::TestCase
  358. def setup
  359. @klass = Class.new do
  360. attr_reader :actions
  361. def save
  362. (@actions ||= []) << :save
  363. :save
  364. end
  365. end
  366. @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  367. @state.state :idling
  368. @state.event :ignite
  369. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
  370. @status.state :second_gear
  371. @status.event :shift_up
  372. @object = @klass.new
  373. @transitions = StateMachine::TransitionCollection.new([
  374. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  375. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  376. ])
  377. @result = @transitions.perform
  378. end
  379. def test_should_succeed
  380. assert_equal :save, @result
  381. end
  382. def test_should_persist_states
  383. assert_equal 'idling', @object.state
  384. assert_equal 'second_gear', @object.status
  385. end
  386. def test_should_run_action_once
  387. assert_equal [:save], @object.actions
  388. end
  389. def test_should_store_results_in_transitions
  390. assert_equal :save, @state_transition.result
  391. assert_equal :save, @status_transition.result
  392. end
  393. end
  394. class TransitionCollectionWithDifferentActionsTest < Test::Unit::TestCase
  395. def setup
  396. @klass = Class.new do
  397. attr_reader :actions
  398. def save_state
  399. (@actions ||= []) << :save_state
  400. :save_state
  401. end
  402. def save_status
  403. (@actions ||= []) << :save_status
  404. :save_status
  405. end
  406. end
  407. @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save_state)
  408. @state.state :idling
  409. @state.event :ignite
  410. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save_status)
  411. @status.state :second_gear
  412. @status.event :shift_up
  413. @object = @klass.new
  414. @transitions = StateMachine::TransitionCollection.new([
  415. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  416. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  417. ])
  418. end
  419. def test_should_succeed
  420. assert_equal true, @transitions.perform
  421. end
  422. def test_should_persist_states
  423. @transitions.perform
  424. assert_equal 'idling', @object.state
  425. assert_equal 'second_gear', @object.status
  426. end
  427. def test_should_run_actions_in_order
  428. @transitions.perform
  429. assert_equal [:save_state, :save_status], @object.actions
  430. end
  431. def test_should_store_results_in_transitions
  432. @transitions.perform
  433. assert_equal :save_state, @state_transition.result
  434. assert_equal :save_status, @status_transition.result
  435. end
  436. def test_should_not_halt_if_action_fails_for_first_transition
  437. @klass.class_eval do
  438. def save_state
  439. (@actions ||= []) << :save_state
  440. false
  441. end
  442. end
  443. assert_equal false, @transitions.perform
  444. assert_equal [:save_state, :save_status], @object.actions
  445. end
  446. def test_should_halt_if_action_fails_for_second_transition
  447. @klass.class_eval do
  448. def save_status
  449. (@actions ||= []) << :save_status
  450. false
  451. end
  452. end
  453. assert_equal false, @transitions.perform
  454. assert_equal [:save_state, :save_status], @object.actions
  455. end
  456. def test_should_rollback_if_action_errors_for_first_transition
  457. @klass.class_eval do
  458. def save_state
  459. raise ArgumentError
  460. end
  461. end
  462. begin; @transitions.perform; rescue; end
  463. assert_equal 'parked', @object.state
  464. assert_equal 'first_gear', @object.status
  465. end
  466. def test_should_rollback_if_action_errors_for_second_transition
  467. @klass.class_eval do
  468. def save_status
  469. raise ArgumentError
  470. end
  471. end
  472. begin; @transitions.perform; rescue; end
  473. assert_equal 'parked', @object.state
  474. assert_equal 'first_gear', @object.status
  475. end
  476. def test_should_not_run_after_callbacks_if_action_fails_for_first_transition
  477. @klass.class_eval do
  478. def save_state
  479. false
  480. end
  481. end
  482. @callbacks = []
  483. @state.after_transition { @callbacks << :state_after }
  484. @state.around_transition {|block| block.call; @callbacks << :state_around }
  485. @status.after_transition { @callbacks << :status_after }
  486. @status.around_transition {|block| block.call; @callbacks << :status_around }
  487. @transitions.perform
  488. assert_equal [], @callbacks
  489. end
  490. def test_should_not_run_after_callbacks_if_action_fails_for_second_transition
  491. @klass.class_eval do
  492. def save_status
  493. false
  494. end
  495. end
  496. @callbacks = []
  497. @state.after_transition { @callbacks << :state_after }
  498. @state.around_transition {|block| block.call; @callbacks << :state_around }
  499. @status.after_transition { @callbacks << :status_after }
  500. @status.around_transition {|block| block.call; @callbacks << :status_around }
  501. @transitions.perform
  502. assert_equal [], @callbacks
  503. end
  504. def test_should_run_after_failure_callbacks_if_action_fails_for_first_transition
  505. @klass.class_eval do
  506. def save_state
  507. false
  508. end
  509. end
  510. @callbacks = []
  511. @state.after_transition(:include_failures => true) { @callbacks << :state_after }
  512. @state.around_transition(:include_failures => true) {|block| block.call; @callbacks << :state_around }
  513. @status.after_transition(:include_failures => true) { @callbacks << :status_after }
  514. @status.around_transition(:include_failures => true) {|block| block.call; @callbacks << :status_around }
  515. @transitions.perform
  516. assert_equal [:status_around, :status_after, :state_around, :state_after], @callbacks
  517. end
  518. def test_should_run_after_failure_callbacks_if_action_fails_for_second_transition
  519. @klass.class_eval do
  520. def save_status
  521. false
  522. end
  523. end
  524. @callbacks = []
  525. @state.after_transition(:include_failures => true) { @callbacks << :state_after }
  526. @state.around_transition(:include_failures => true) {|block| block.call; @callbacks << :state_around }
  527. @status.after_transition(:include_failures => true) { @callbacks << :status_after }
  528. @status.around_transition(:include_failures => true) {|block| block.call; @callbacks << :status_around }
  529. @transitions.perform
  530. assert_equal [:status_around, :status_after, :state_around, :state_after], @callbacks
  531. end
  532. end
  533. class TransitionCollectionWithMixedActionsTest < Test::Unit::TestCase
  534. def setup
  535. @klass = Class.new do
  536. def save
  537. true
  538. end
  539. end
  540. @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  541. @state.state :idling
  542. @state.event :ignite
  543. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear)
  544. @status.state :second_gear
  545. @status.event :shift_up
  546. @object = @klass.new
  547. @transitions = StateMachine::TransitionCollection.new([
  548. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  549. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  550. ])
  551. @result = @transitions.perform
  552. end
  553. def test_should_succeed
  554. assert_equal true, @result
  555. end
  556. def test_should_persist_states
  557. assert_equal 'idling', @object.state
  558. assert_equal 'second_gear', @object.status
  559. end
  560. def test_should_store_results_in_transitions
  561. assert_equal true, @state_transition.result
  562. assert_nil @status_transition.result
  563. end
  564. end
  565. class TransitionCollectionWithBlockTest < Test::Unit::TestCase
  566. def setup
  567. @klass = Class.new do
  568. attr_reader :actions
  569. def save
  570. (@actions ||= []) << :save
  571. end
  572. end
  573. @state = StateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
  574. @state.state :idling
  575. @state.event :ignite
  576. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
  577. @status.state :second_gear
  578. @status.event :shift_up
  579. @object = @klass.new
  580. @transitions = StateMachine::TransitionCollection.new([
  581. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  582. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  583. ])
  584. @result = @transitions.perform { 1 }
  585. end
  586. def test_should_succeed
  587. assert_equal 1, @result
  588. end
  589. def test_should_persist_states
  590. assert_equal 'idling', @object.state
  591. assert_equal 'second_gear', @object.status
  592. end
  593. def test_should_not_run_machine_actions
  594. assert_nil @object.actions
  595. end
  596. def test_should_use_result_as_transition_result
  597. assert_equal 1, @state_transition.result
  598. assert_equal 1, @status_transition.result
  599. end
  600. end
  601. class TransitionCollectionWithActionFailedTest < Test::Unit::TestCase
  602. def setup
  603. @klass = Class.new do
  604. def save
  605. false
  606. end
  607. end
  608. @before_count = 0
  609. @around_before_count = 0
  610. @after_count = 0
  611. @around_after_count = 0
  612. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  613. @machine.state :idling
  614. @machine.event :ignite
  615. @machine.before_transition {@before_count += 1}
  616. @machine.after_transition {@after_count += 1}
  617. @machine.after_transition(:include_failures => true) {@after_count += 1}
  618. @machine.around_transition {|block| @around_before_count += 1; block.call; @around_after_count += 1}
  619. @machine.around_transition(:include_failures => true) {|block| @around_before_count += 1; block.call; @around_after_count += 1}
  620. @object = @klass.new
  621. @transitions = StateMachine::TransitionCollection.new([
  622. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  623. ])
  624. @result = @transitions.perform
  625. end
  626. def test_should_not_succeed
  627. assert_equal false, @result
  628. end
  629. def test_should_not_persist_state
  630. assert_equal 'parked', @object.state
  631. end
  632. def test_should_run_before_callbacks
  633. assert_equal 1, @before_count
  634. end
  635. def test_should_run_around_callbacks_before_yield
  636. assert_equal 2, @around_before_count
  637. end
  638. def test_should_only_run_after_callbacks_that_include_failures
  639. assert_equal 1, @after_count
  640. end
  641. def test_should_only_run_around_callbacks_after_yield_that_include_failures
  642. assert_equal 1, @around_after_count
  643. end
  644. end
  645. class TransitionCollectionWithActionErrorTest < Test::Unit::TestCase
  646. def setup
  647. @klass = Class.new do
  648. def save
  649. raise ArgumentError
  650. end
  651. end
  652. @before_count = 0
  653. @around_before_count = 0
  654. @after_count = 0
  655. @around_after_count = 0
  656. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  657. @machine.state :idling
  658. @machine.event :ignite
  659. @machine.before_transition {@before_count += 1}
  660. @machine.after_transition {@after_count += 1}
  661. @machine.after_transition(:include_failures => true) {@after_count += 1}
  662. @machine.around_transition {|block| @around_before_count += 1; block.call; @around_after_count += 1}
  663. @machine.around_transition(:include_failures => true) {|block| @around_before_count += 1; block.call; @around_after_count += 1}
  664. @object = @klass.new
  665. @transitions = StateMachine::TransitionCollection.new([
  666. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  667. ])
  668. @raised = true
  669. begin
  670. @transitions.perform
  671. @raised = false
  672. rescue ArgumentError
  673. end
  674. end
  675. def test_should_not_catch_exception
  676. assert @raised
  677. end
  678. def test_should_not_persist_state
  679. assert_equal 'parked', @object.state
  680. end
  681. def test_should_run_before_callbacks
  682. assert_equal 1, @before_count
  683. end
  684. def test_should_run_around_callbacks_before_yield
  685. assert_equal 2, @around_before_count
  686. end
  687. def test_should_not_run_after_callbacks
  688. assert_equal 0, @after_count
  689. end
  690. def test_should_not_run_around_callbacks_after_yield
  691. assert_equal 0, @around_after_count
  692. end
  693. end
  694. class TransitionCollectionWithCallbacksTest < Test::Unit::TestCase
  695. def setup
  696. @klass = Class.new do
  697. attr_reader :saved
  698. def save
  699. @saved = true
  700. end
  701. end
  702. @before_callbacks = []
  703. @after_callbacks = []
  704. @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  705. @state.state :idling
  706. @state.event :ignite
  707. @state.before_transition {@before_callbacks << :state_before}
  708. @state.after_transition(:include_failures => true) {@after_callbacks << :state_after}
  709. @state.around_transition(:include_failures => true) {|block| @before_callbacks << :state_around; block.call; @after_callbacks << :state_around}
  710. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
  711. @status.state :second_gear
  712. @status.event :shift_up
  713. @status.before_transition {@before_callbacks << :status_before}
  714. @status.after_transition(:include_failures => true) {@after_callbacks << :status_after}
  715. @status.around_transition(:include_failures => true) {|block| @before_callbacks << :status_around; block.call; @after_callbacks << :status_around}
  716. @object = @klass.new
  717. @transitions = StateMachine::TransitionCollection.new([
  718. StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  719. StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  720. ])
  721. end
  722. def test_should_run_before_callbacks_in_order
  723. @transitions.perform
  724. assert_equal [:state_before, :state_around, :status_before, :status_around], @before_callbacks
  725. end
  726. def test_should_halt_if_before_callback_halted_for_first_transition
  727. @state.before_transition {throw :halt}
  728. assert_equal false, @transitions.perform
  729. assert_equal [:state_before, :state_around], @before_callbacks
  730. end
  731. def test_should_halt_if_before_callback_halted_for_second_transition
  732. @status.before_transition {throw :halt}
  733. assert_equal false, @transitions.perform
  734. assert_equal [:state_before, :state_around, :status_before, :status_around], @before_callbacks
  735. end
  736. def test_should_halt_if_around_callback_halted_before_yield_for_first_transition
  737. @state.around_transition {throw :halt}
  738. assert_equal false, @transitions.perform
  739. assert_equal [:state_before, :state_around], @before_callbacks
  740. end
  741. def test_should_halt_if_around_callback_halted_before_yield_for_second_transition
  742. @status.around_transition {throw :halt}
  743. assert_equal false, @transitions.perform
  744. assert_equal [:state_before, :state_around, :status_before, :status_around], @before_callbacks
  745. end
  746. def test_should_run_after_callbacks_in_reverse_order
  747. @transitions.perform
  748. assert_equal [:status_around, :status_after, :state_around, :state_after], @after_callbacks
  749. end
  750. def test_should_not_halt_if_after_callback_halted_for_first_transition
  751. @state.after_transition(:include_failures => true) {throw :halt}
  752. assert_equal true, @transitions.perform
  753. assert_equal [:status_around, :status_after, :state_around, :state_after], @after_callbacks
  754. end
  755. def test_should_not_halt_if_around_callback_halted_for_second_transition
  756. @status.around_transition(:include_failures => true) {|block| block.call; throw :halt}
  757. assert_equal true, @transitions.perform
  758. assert_equal [:state_around, :state_after], @after_callbacks
  759. end
  760. def test_should_run_before_callbacks_before_persisting_the_state
  761. @state.before_transition {|object| @before_state = object.state}
  762. @state.around_transition {|object, transition, block| @around_state = object.state; block.call}
  763. @transitions.perform
  764. assert_equal 'parked', @before_state
  765. assert_equal 'parked', @around_state
  766. end
  767. def test_should_persist_state_before_running_action
  768. @klass.class_eval do
  769. attr_reader :saved_on_persist
  770. def state=(value)
  771. @state = value
  772. @saved_on_persist = @saved
  773. end
  774. end
  775. @transitions.perform
  776. assert !@object.saved_on_persist
  777. end
  778. def test_should_persist_state_before_running_action_block
  779. @klass.class_eval do
  780. attr_writer :saved
  781. attr_reader :saved_on_persist
  782. def state=(value)
  783. @state = value
  784. @saved_on_persist = @saved
  785. end
  786. end
  787. @transitions.perform { @object.saved = true }
  788. assert !@object.saved_on_persist
  789. end
  790. def test_should_run_after_callbacks_after_running_the_action
  791. @state.after_transition {|object| @after_saved = object.saved}
  792. @state.around_transition {|object, transition, block| block.call; @around_saved = object.saved}
  793. @transitions.perform
  794. assert @after_saved
  795. assert @around_saved
  796. end
  797. end
  798. class TransitionCollectionWithBeforeCallbackHaltTest < Test::Unit::TestCase
  799. def setup
  800. @klass = Class.new do
  801. attr_reader :saved
  802. def save
  803. @saved = true
  804. end
  805. end
  806. @before_count = 0
  807. @after_count = 0
  808. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  809. @machine.state :idling
  810. @machine.event :ignite
  811. @machine.before_transition {@before_count += 1; throw :halt}
  812. @machine.before_transition {@before_count += 1}
  813. @machine.after_transition {@after_count += 1}
  814. @machine.around_transition {|block| @before_count += 1; block.call; @after_count += 1}
  815. @object = @klass.new
  816. @transitions = StateMachine::TransitionCollection.new([
  817. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  818. ])
  819. @result = @transitions.perform
  820. end
  821. def test_should_not_succeed
  822. assert_equal false, @result
  823. end
  824. def test_should_not_persist_state
  825. assert_equal 'parked', @object.state
  826. end
  827. def test_should_not_run_action
  828. assert !@object.saved
  829. end
  830. def test_should_not_run_further_before_callbacks
  831. assert_equal 1, @before_count
  832. end
  833. def test_should_not_run_after_callbacks
  834. assert_equal 0, @after_count
  835. end
  836. end
  837. class TransitionCollectionWithAfterCallbackHaltTest < Test::Unit::TestCase
  838. def setup
  839. @klass = Class.new do
  840. attr_reader :saved
  841. def save
  842. @saved = true
  843. end
  844. end
  845. @before_count = 0
  846. @after_count = 0
  847. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  848. @machine.state :idling
  849. @machine.event :ignite
  850. @machine.before_transition {@before_count += 1}
  851. @machine.after_transition {@after_count += 1; throw :halt}
  852. @machine.after_transition {@after_count += 1}
  853. @machine.around_transition {|block| @before_count += 1; block.call; @after_count += 1}
  854. @object = @klass.new
  855. @transitions = StateMachine::TransitionCollection.new([
  856. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  857. ])
  858. @result = @transitions.perform
  859. end
  860. def test_should_succeed
  861. assert_equal true, @result
  862. end
  863. def test_should_persist_state
  864. assert_equal 'idling', @object.state
  865. end
  866. def test_should_run_before_callbacks
  867. assert_equal 2, @before_count
  868. end
  869. def test_should_not_run_further_after_callbacks
  870. assert_equal 2, @after_count
  871. end
  872. end
  873. class TransitionCollectionWithSkippedAfterCallbacksTest < Test::Unit::TestCase
  874. def setup
  875. @klass = Class.new
  876. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  877. @machine.state :idling
  878. @machine.event :ignite
  879. @machine.after_transition {@ran_after = true}
  880. @machine.around_transition {|block| @ran_around_before = true; block.call; @ran_around_after = true}
  881. @object = @klass.new
  882. @transitions = StateMachine::TransitionCollection.new([
  883. @transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  884. ], :after => false)
  885. @result = @transitions.perform
  886. end
  887. def test_should_succeed
  888. assert_equal true, @result
  889. end
  890. def test_should_not_run_after_callbacks
  891. assert !@ran_after
  892. end
  893. def test_should_not_run_around_callbacks_after_yield
  894. assert !@ran_around_after
  895. end
  896. def test_should_run_after_callbacks_on_subsequent_perform
  897. StateMachine::TransitionCollection.new([@transition]).perform
  898. assert @ran_after
  899. end
  900. def test_should_run_around_callbacks_after_yield_on_subsequent_perform
  901. StateMachine::TransitionCollection.new([@transition]).perform
  902. assert @ran_around_after
  903. end
  904. def test_should_not_rerun_around_callbacks_before_yield_on_subsequent_perform
  905. @ran_around_before = false
  906. StateMachine::TransitionCollection.new([@transition]).perform
  907. assert !@ran_around_before
  908. end
  909. end
  910. class TransitionCollectionWithActionHelperBaseTest < Test::Unit::TestCase
  911. def setup
  912. @superclass = Class.new do
  913. def save
  914. true
  915. end
  916. end
  917. @klass = Class.new(@superclass) do
  918. attr_reader :saved, :state_on_save, :state_event_on_save, :state_event_transition_on_save
  919. def save
  920. @saved = true
  921. @state_on_save = state
  922. @state_event_on_save = state_event
  923. @state_event_transition_on_save = state_event_transition
  924. super
  925. end
  926. end
  927. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  928. @machine.state :idling
  929. @machine.event :ignite
  930. @object = @klass.new
  931. @transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  932. end
  933. def default_test
  934. end
  935. end
  936. class TransitionCollectionWithActionHelperAndSkippedActionTest < TransitionCollectionWithActionHelperBaseTest
  937. def setup
  938. super
  939. @result = StateMachine::TransitionCollection.new([@transition], :actions => false).perform
  940. end
  941. def test_should_succeed
  942. assert_equal true, @result
  943. end
  944. def test_should_not_run_action
  945. assert !@object.saved
  946. end
  947. end
  948. class TransitionCollectionWithActionHelperAndSkippedAfterCallbacksTest < TransitionCollectionWithActionHelperBaseTest
  949. def setup
  950. super
  951. @result = StateMachine::TransitionCollection.new([@transition], :after => false).perform
  952. end
  953. def test_should_succeed
  954. assert_equal true, @result
  955. end
  956. def test_should_run_action
  957. assert @object.saved
  958. end
  959. def test_should_have_already_persisted_when_running_action
  960. assert_equal 'idling', @object.state_on_save
  961. end
  962. def test_should_not_have_event_during_action
  963. assert_nil @object.state_event_on_save
  964. end
  965. def test_should_not_write_event
  966. assert_nil @object.state_event
  967. end
  968. def test_should_not_have_event_transition_during_save
  969. assert_nil @object.state_event_transition_on_save
  970. end
  971. def test_should_not_write_event_attribute
  972. assert_nil @object.send(:state_event_transition)
  973. end
  974. end
  975. class TransitionCollectionWithActionHelperAndBlockTest < TransitionCollectionWithActionHelperBaseTest
  976. def setup
  977. super
  978. @result = StateMachine::TransitionCollection.new([@transition]).perform { true }
  979. end
  980. def test_should_succeed
  981. assert_equal true, @result
  982. end
  983. def test_should_not_run_action
  984. assert !@object.saved
  985. end
  986. end
  987. class TransitionCollectionWithActionHelperInvalidTest < TransitionCollectionWithActionHelperBaseTest
  988. def setup
  989. super
  990. @result = StateMachine::TransitionCollection.new([@transition, nil]).perform
  991. end
  992. def test_should_not_succeed
  993. assert_equal false, @result
  994. end
  995. def test_should_not_run_action
  996. assert !@object.saved
  997. end
  998. end
  999. class TransitionCollectionWithActionHelperWithNilActionTest < TransitionCollectionWithActionHelperBaseTest
  1000. def setup
  1001. super
  1002. @machine = StateMachine::Machine.new(@klass, :status, :initial => :parked)
  1003. @machine.state :idling
  1004. @machine.event :ignite
  1005. @result = StateMachine::TransitionCollection.new([@transition, StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)]).perform
  1006. end
  1007. def test_should_succeed
  1008. assert_equal true, @result
  1009. end
  1010. def test_should_run_action
  1011. assert @object.saved
  1012. end
  1013. def test_should_have_already_persisted_when_running_action
  1014. assert_equal 'idling', @object.state_on_save
  1015. end
  1016. def test_should_not_have_event_during_action
  1017. assert_nil @object.state_event_on_save
  1018. end
  1019. def test_should_not_write_event
  1020. assert_nil @object.state_event
  1021. end
  1022. def test_should_not_have_event_transition_during_save
  1023. assert_nil @object.state_event_transition_on_save
  1024. end
  1025. def test_should_not_write_event_attribute
  1026. assert_nil @object.send(:state_event_transition)
  1027. end
  1028. end
  1029. class TransitionCollectionWithActionHelperWithDifferentActionsTest < TransitionCollectionWithActionHelperBaseTest
  1030. def setup
  1031. super
  1032. @klass.class_eval do
  1033. def save_status
  1034. true
  1035. end
  1036. end
  1037. @machine = StateMachine::Machine.new(@klass, :status, :initial => :parked, :action => :save_status)
  1038. @machine.state :idling
  1039. @machine.event :ignite
  1040. @result = StateMachine::TransitionCollection.new([@transition, StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)]).perform
  1041. end
  1042. def test_should_succeed
  1043. assert_equal true, @result
  1044. end
  1045. def test_should_run_action
  1046. assert @object.saved
  1047. end
  1048. def test_should_have_already_persisted_when_running_action
  1049. assert_equal 'idling', @object.state_on_save
  1050. end
  1051. def test_should_not_have_event_during_action
  1052. assert_nil @object.state_event_on_save
  1053. end
  1054. def test_should_not_write_event
  1055. assert_nil @object.state_event
  1056. end
  1057. def test_should_not_have_event_transition_during_save
  1058. assert_nil @object.state_event_transition_on_save
  1059. end
  1060. def test_should_not_write_event_attribute
  1061. assert_nil @object.send(:state_event_transition)
  1062. end
  1063. end
  1064. class TransitionCollectionWithActionHelperTest < TransitionCollectionWithActionHelperBaseTest
  1065. def setup
  1066. super
  1067. @result = StateMachine::TransitionCollection.new([@transition]).perform
  1068. end
  1069. def test_should_succeed
  1070. assert_equal true, @result
  1071. end
  1072. def test_should_run_action
  1073. assert @object.saved
  1074. end
  1075. def test_should_not_have_already_persisted_when_running_action
  1076. assert_equal 'parked', @object.state_on_save
  1077. end
  1078. def test_should_persist
  1079. assert_equal 'idling', @object.state
  1080. end
  1081. def test_should_not_have_event_during_action
  1082. assert_nil @object.state_event_on_save
  1083. end
  1084. def test_should_not_write_event
  1085. assert_nil @object.state_event
  1086. end
  1087. def test_should_have_event_transition_during_action
  1088. assert_equal @transition, @object.state_event_transition_on_save
  1089. end
  1090. def test_should_not_write_event_transition
  1091. assert_nil @object.send(:state_event_transition)
  1092. end
  1093. def test_should_mark_event_transition_as_transient
  1094. assert @transition.transient?
  1095. end
  1096. end
  1097. class TransitionCollectionWithActionHelperMultipleTest < TransitionCollectionWithActionHelperBaseTest
  1098. def setup
  1099. super
  1100. @status_machine = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
  1101. @status_machine.state :second_gear
  1102. @status_machine.event :shift_up
  1103. @klass.class_eval do
  1104. attr_reader :status_on_save, :status_event_on_save, :status_event_transition_on_save
  1105. def save
  1106. @saved = true
  1107. @state_on_save = state
  1108. @state_event_on_save = state_event
  1109. @state_event_transition_on_save = state_event_transition
  1110. @status_on_save = status
  1111. @status_event_on_save = status_event
  1112. @status_event_transition_on_save = status_event_transition
  1113. super
  1114. 1
  1115. end
  1116. end
  1117. @object = @klass.new
  1118. @state_transition = StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  1119. @status_transition = StateMachine::Transition.new(@object, @status_machine, :shift_up, :first_gear, :second_gear)
  1120. @result = StateMachine::TransitionCollection.new([@state_transition, @status_transition]).perform
  1121. end
  1122. def test_should_succeed
  1123. assert_equal 1, @result
  1124. end
  1125. def test_should_run_action
  1126. assert @object.saved
  1127. end
  1128. def test_should_not_have_already_persisted_when_running_action
  1129. assert_equal 'parked', @object.state_on_save
  1130. assert_equal 'first_gear', @object.status_on_save
  1131. end
  1132. def test_should_persist
  1133. assert_equal 'idling', @object.state
  1134. assert_equal 'second_gear', @object.status
  1135. end
  1136. def test_should_not_have_events_during_action
  1137. assert_nil @object.state_event_on_save
  1138. assert_nil @object.status_event_on_save
  1139. end
  1140. def test_should_not_write_events
  1141. assert_nil @object.state_event
  1142. assert_nil @object.status_event
  1143. end
  1144. def test_should_have_event_transitions_during_action
  1145. assert_equal @state_transition, @object.state_event_transition_on_save
  1146. assert_equal @status_transition, @object.status_event_transition_on_save
  1147. end
  1148. def test_should_not_write_event_transitions
  1149. assert_nil @object.send(:state_event_transition)
  1150. assert_nil @object.send(:status_event_transition)
  1151. end
  1152. def test_should_mark_event_transitions_as_transient
  1153. assert @state_transition.transient?
  1154. assert @status_transition.transient?
  1155. end
  1156. end
  1157. class TransitionCollectionWithActionHelperErrorTest < TransitionCollectionWithActionHelperBaseTest
  1158. def setup
  1159. super
  1160. @superclass.class_eval do
  1161. def save
  1162. raise ArgumentError
  1163. end
  1164. end
  1165. begin; StateMachine::TransitionCollection.new([@transition]).perform; rescue; end
  1166. end
  1167. def test_should_not_write_event
  1168. assert_nil @object.state_event
  1169. end
  1170. def test_should_not_write_event_transition
  1171. assert_nil @object.send(:state_event_transition)
  1172. end
  1173. end
  1174. class AttributeTransitionCollectionByDefaultTest < Test::Unit::TestCase
  1175. def setup
  1176. @transitions = StateMachine::AttributeTransitionCollection.new
  1177. end
  1178. def test_should_skip_actions
  1179. assert @transitions.skip_actions
  1180. end
  1181. def test_should_not_skip_after
  1182. assert !@transitions.skip_after
  1183. end
  1184. def test_should_not_use_transaction
  1185. assert !@transitions.use_transaction
  1186. end
  1187. def test_should_be_empty
  1188. assert @transitions.empty?
  1189. end
  1190. end
  1191. class AttributeTransitionCollectionWithEventsTest < Test::Unit::TestCase
  1192. def setup
  1193. @klass = Class.new
  1194. @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1195. @state.state :idling
  1196. @state.event :ignite
  1197. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
  1198. @status.state :second_gear
  1199. @status.event :shift_up
  1200. @object = @klass.new
  1201. @object.state_event = 'ignite'
  1202. @object.status_event = 'shift_up'
  1203. @transitions = StateMachine::AttributeTransitionCollection.new([
  1204. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  1205. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  1206. ])
  1207. @result = @transitions.perform
  1208. end
  1209. def test_should_succeed
  1210. assert_equal true, @result
  1211. end
  1212. def test_should_persist_states
  1213. assert_equal 'idling', @object.state
  1214. assert_equal 'second_gear', @object.status
  1215. end
  1216. def test_should_clear_events
  1217. assert_nil @object.state_event
  1218. assert_nil @object.status_event
  1219. end
  1220. def test_should_not_write_event_transitions
  1221. assert_nil @object.send(:state_event_transition)
  1222. assert_nil @object.send(:status_event_transition)
  1223. end
  1224. end
  1225. class AttributeTransitionCollectionWithEventTransitionsTest < Test::Unit::TestCase
  1226. def setup
  1227. @klass = Class.new
  1228. @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1229. @state.state :idling
  1230. @state.event :ignite
  1231. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
  1232. @status.state :second_gear
  1233. @status.event :shift_up
  1234. @object = @klass.new
  1235. @object.send(:state_event_transition=, @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling))
  1236. @object.send(:status_event_transition=, @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear))
  1237. @transitions = StateMachine::AttributeTransitionCollection.new([@state_transition, @status_transition])
  1238. @result = @transitions.perform
  1239. end
  1240. def test_should_succeed
  1241. assert_equal true, @result
  1242. end
  1243. def test_should_persist_states
  1244. assert_equal 'idling', @object.state
  1245. assert_equal 'second_gear', @object.status
  1246. end
  1247. def test_should_not_write_events
  1248. assert_nil @object.state_event
  1249. assert_nil @object.status_event
  1250. end
  1251. def test_should_clear_event_transitions
  1252. assert_nil @object.send(:state_event_transition)
  1253. assert_nil @object.send(:status_event_transition)
  1254. end
  1255. end
  1256. class AttributeTransitionCollectionWithActionFailedTest < Test::Unit::TestCase
  1257. def setup
  1258. @klass = Class.new
  1259. @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1260. @state.state :idling
  1261. @state.event :ignite
  1262. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
  1263. @status.state :second_gear
  1264. @status.event :shift_up
  1265. @object = @klass.new
  1266. @object.state_event = 'ignite'
  1267. @object.status_event = 'shift_up'
  1268. @transitions = StateMachine::AttributeTransitionCollection.new([
  1269. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  1270. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  1271. ])
  1272. @result = @transitions.perform { false }
  1273. end
  1274. def test_should_not_succeed
  1275. assert_equal false, @result
  1276. end
  1277. def test_should_not_persist_states
  1278. assert_equal 'parked', @object.state
  1279. assert_equal 'first_gear', @object.status
  1280. end
  1281. def test_should_not_clear_events
  1282. assert_equal :ignite, @object.state_event
  1283. assert_equal :shift_up, @object.status_event
  1284. end
  1285. def test_should_not_write_event_transitions
  1286. assert_nil @object.send(:state_event_transition)
  1287. assert_nil @object.send(:status_event_transition)
  1288. end
  1289. end
  1290. class AttributeTransitionCollectionWithActionErrorTest < Test::Unit::TestCase
  1291. def setup
  1292. @klass = Class.new
  1293. @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1294. @state.state :idling
  1295. @state.event :ignite
  1296. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
  1297. @status.state :second_gear
  1298. @status.event :shift_up
  1299. @object = @klass.new
  1300. @object.state_event = 'ignite'
  1301. @object.status_event = 'shift_up'
  1302. @transitions = StateMachine::AttributeTransitionCollection.new([
  1303. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  1304. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  1305. ])
  1306. begin; @transitions.perform { raise ArgumentError }; rescue; end
  1307. end
  1308. def test_should_not_persist_states
  1309. assert_equal 'parked', @object.state
  1310. assert_equal 'first_gear', @object.status
  1311. end
  1312. def test_should_not_clear_events
  1313. assert_equal :ignite, @object.state_event
  1314. assert_equal :shift_up, @object.status_event
  1315. end
  1316. def test_should_not_write_event_transitions
  1317. assert_nil @object.send(:state_event_transition)
  1318. assert_nil @object.send(:status_event_transition)
  1319. end
  1320. end
  1321. class AttributeTransitionCollectionWithCallbacksTest < Test::Unit::TestCase
  1322. def setup
  1323. @klass = Class.new
  1324. @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1325. @state.state :idling
  1326. @state.event :ignite
  1327. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
  1328. @status.state :second_gear
  1329. @status.event :shift_up
  1330. @object = @klass.new
  1331. @transitions = StateMachine::AttributeTransitionCollection.new([
  1332. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  1333. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  1334. ])
  1335. end
  1336. def test_should_not_have_events_during_before_callbacks
  1337. @state.before_transition {|object, transition| @before_state_event = object.state_event }
  1338. @state.around_transition {|object, transition, block| @around_state_event = object.state_event; block.call }
  1339. @transitions.perform
  1340. assert_nil @before_state_event
  1341. assert_nil @around_state_event
  1342. end
  1343. def test_should_not_have_events_during_action
  1344. @transitions.perform { @state_event = @object.state_event }
  1345. assert_nil @state_event
  1346. end
  1347. def test_should_not_have_events_during_after_callbacks
  1348. @state.after_transition {|object, transition| @after_state_event = object.state_event }
  1349. @state.around_transition {|object, transition, block| block.call; @around_state_event = object.state_event }
  1350. @transitions.perform
  1351. assert_nil @state_event
  1352. end
  1353. def test_should_not_have_event_transitions_during_before_callbacks
  1354. @state.before_transition {|object, transition| @state_event_transition = object.send(:state_event_transition) }
  1355. @transitions.perform
  1356. assert_nil @state_event_transition
  1357. end
  1358. def test_should_not_have_event_transitions_during_action
  1359. @transitions.perform { @state_event_transition = @object.send(:state_event_transition) }
  1360. assert_nil @state_event_transition
  1361. end
  1362. def test_should_not_have_event_transitions_during_after_callbacks
  1363. @state.after_transition {|object, transition| @after_state_event_transition = object.send(:state_event_transition) }
  1364. @state.around_transition {|object, transition, block| block.call; @around_state_event_transition = object.send(:state_event_transition) }
  1365. @transitions.perform
  1366. assert_nil @after_state_event_transition
  1367. assert_nil @around_state_event_transition
  1368. end
  1369. end
  1370. class AttributeTransitionCollectionWithBeforeCallbackHaltTest < Test::Unit::TestCase
  1371. def setup
  1372. @klass = Class.new
  1373. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1374. @machine.state :idling
  1375. @machine.event :ignite
  1376. @machine.before_transition {throw :halt}
  1377. @object = @klass.new
  1378. @object.state_event = 'ignite'
  1379. @transitions = StateMachine::AttributeTransitionCollection.new([
  1380. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  1381. ])
  1382. @result = @transitions.perform
  1383. end
  1384. def test_should_not_succeed
  1385. assert_equal false, @result
  1386. end
  1387. def test_should_not_clear_event
  1388. assert_equal :ignite, @object.state_event
  1389. end
  1390. def test_should_not_write_event_transition
  1391. assert_nil @object.send(:state_event_transition)
  1392. end
  1393. end
  1394. class AttributeTransitionCollectionWithBeforeCallbackErrorTest < Test::Unit::TestCase
  1395. def setup
  1396. @klass = Class.new
  1397. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1398. @machine.state :idling
  1399. @machine.event :ignite
  1400. @machine.before_transition {raise ArgumentError}
  1401. @object = @klass.new
  1402. @object.state_event = 'ignite'
  1403. @transitions = StateMachine::AttributeTransitionCollection.new([
  1404. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  1405. ])
  1406. begin; @transitions.perform; rescue; end
  1407. end
  1408. def test_should_not_clear_event
  1409. assert_equal :ignite, @object.state_event
  1410. end
  1411. def test_should_not_write_event_transition
  1412. assert_nil @object.send(:state_event_transition)
  1413. end
  1414. end
  1415. class AttributeTransitionCollectionWithAroundCallbackBeforeYieldHaltTest < Test::Unit::TestCase
  1416. def setup
  1417. @klass = Class.new
  1418. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1419. @machine.state :idling
  1420. @machine.event :ignite
  1421. @machine.around_transition {throw :halt}
  1422. @object = @klass.new
  1423. @object.state_event = 'ignite'
  1424. @transitions = StateMachine::AttributeTransitionCollection.new([
  1425. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  1426. ])
  1427. @result = @transitions.perform
  1428. end
  1429. def test_should_not_succeed
  1430. assert_equal false, @result
  1431. end
  1432. def test_should_not_clear_event
  1433. assert_equal :ignite, @object.state_event
  1434. end
  1435. def test_should_not_write_event_transition
  1436. assert_nil @object.send(:state_event_transition)
  1437. end
  1438. end
  1439. class AttributeTransitionCollectionWithAroundAfterYieldCallbackErrorTest < Test::Unit::TestCase
  1440. def setup
  1441. @klass = Class.new
  1442. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1443. @machine.state :idling
  1444. @machine.event :ignite
  1445. @machine.before_transition {raise ArgumentError}
  1446. @object = @klass.new
  1447. @object.state_event = 'ignite'
  1448. @transitions = StateMachine::AttributeTransitionCollection.new([
  1449. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  1450. ])
  1451. begin; @transitions.perform; rescue; end
  1452. end
  1453. def test_should_not_clear_event
  1454. assert_equal :ignite, @object.state_event
  1455. end
  1456. def test_should_not_write_event_transition
  1457. assert_nil @object.send(:state_event_transition)
  1458. end
  1459. end
  1460. class AttributeTransitionCollectionWithSkippedAfterCallbacksTest < Test::Unit::TestCase
  1461. def setup
  1462. @klass = Class.new
  1463. @state = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1464. @state.state :idling
  1465. @state.event :ignite
  1466. @status = StateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
  1467. @status.state :second_gear
  1468. @status.event :shift_up
  1469. @object = @klass.new
  1470. @object.state_event = 'ignite'
  1471. @object.status_event = 'shift_up'
  1472. @transitions = StateMachine::AttributeTransitionCollection.new([
  1473. @state_transition = StateMachine::Transition.new(@object, @state, :ignite, :parked, :idling),
  1474. @status_transition = StateMachine::Transition.new(@object, @status, :shift_up, :first_gear, :second_gear)
  1475. ], :after => false)
  1476. end
  1477. def test_should_clear_events
  1478. @transitions.perform
  1479. assert_nil @object.state_event
  1480. assert_nil @object.status_event
  1481. end
  1482. def test_should_write_event_transitions_if_success
  1483. @transitions.perform { true }
  1484. assert_equal @state_transition, @object.send(:state_event_transition)
  1485. assert_equal @status_transition, @object.send(:status_event_transition)
  1486. end
  1487. def test_should_not_write_event_transitions_if_failed
  1488. @transitions.perform { false }
  1489. assert_nil @object.send(:state_event_transition)
  1490. assert_nil @object.send(:status_event_transition)
  1491. end
  1492. end
  1493. class AttributeTransitionCollectionWithAfterCallbackHaltTest < Test::Unit::TestCase
  1494. def setup
  1495. @klass = Class.new
  1496. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1497. @machine.state :idling
  1498. @machine.event :ignite
  1499. @machine.after_transition {throw :halt}
  1500. @object = @klass.new
  1501. @object.state_event = 'ignite'
  1502. @transitions = StateMachine::AttributeTransitionCollection.new([
  1503. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  1504. ])
  1505. @result = @transitions.perform
  1506. end
  1507. def test_should_succeed
  1508. assert_equal true, @result
  1509. end
  1510. def test_should_clear_event
  1511. assert_nil @object.state_event
  1512. end
  1513. def test_should_not_write_event_transition
  1514. assert_nil @object.send(:state_event_transition)
  1515. end
  1516. end
  1517. class AttributeTransitionCollectionWithAfterCallbackErrorTest < Test::Unit::TestCase
  1518. def setup
  1519. @klass = Class.new
  1520. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1521. @machine.state :idling
  1522. @machine.event :ignite
  1523. @machine.after_transition {raise ArgumentError}
  1524. @object = @klass.new
  1525. @object.state_event = 'ignite'
  1526. @transitions = StateMachine::AttributeTransitionCollection.new([
  1527. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  1528. ])
  1529. begin; @transitions.perform; rescue; end
  1530. end
  1531. def test_should_clear_event
  1532. assert_nil @object.state_event
  1533. end
  1534. def test_should_not_write_event_transition
  1535. assert_nil @object.send(:state_event_transition)
  1536. end
  1537. end
  1538. class AttributeTransitionCollectionWithAroundCallbackAfterYieldHaltTest < Test::Unit::TestCase
  1539. def setup
  1540. @klass = Class.new
  1541. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1542. @machine.state :idling
  1543. @machine.event :ignite
  1544. @machine.around_transition {|block| block.call; throw :halt}
  1545. @object = @klass.new
  1546. @object.state_event = 'ignite'
  1547. @transitions = StateMachine::AttributeTransitionCollection.new([
  1548. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  1549. ])
  1550. @result = @transitions.perform
  1551. end
  1552. def test_should_succeed
  1553. assert_equal true, @result
  1554. end
  1555. def test_should_clear_event
  1556. assert_nil @object.state_event
  1557. end
  1558. def test_should_not_write_event_transition
  1559. assert_nil @object.send(:state_event_transition)
  1560. end
  1561. end
  1562. class AttributeTransitionCollectionWithAfterCallbackErrorTest < Test::Unit::TestCase
  1563. def setup
  1564. @klass = Class.new
  1565. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1566. @machine.state :idling
  1567. @machine.event :ignite
  1568. @machine.around_transition {|block| block.call; raise ArgumentError}
  1569. @object = @klass.new
  1570. @object.state_event = 'ignite'
  1571. @transitions = StateMachine::AttributeTransitionCollection.new([
  1572. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  1573. ])
  1574. begin; @transitions.perform; rescue; end
  1575. end
  1576. def test_should_clear_event
  1577. assert_nil @object.state_event
  1578. end
  1579. def test_should_not_write_event_transition
  1580. assert_nil @object.send(:state_event_transition)
  1581. end
  1582. end
  1583. class AttributeTransitionCollectionMarshallingTest < Test::Unit::TestCase
  1584. def setup
  1585. @klass = Class.new
  1586. self.class.const_set('Example', @klass)
  1587. @machine = StateMachine::Machine.new(@klass, :initial => :parked, :action => :save)
  1588. @machine.state :idling
  1589. @machine.event :ignite
  1590. @object = @klass.new
  1591. @object.state_event = 'ignite'
  1592. end
  1593. def test_should_marshal_during_before_callbacks
  1594. @machine.before_transition {|object, transition| Marshal.dump(object)}
  1595. assert_nothing_raised do
  1596. transitions(:after => false).perform { true }
  1597. transitions.perform { true }
  1598. end
  1599. end
  1600. def test_should_marshal_during_action
  1601. assert_nothing_raised do
  1602. transitions(:after => false).perform do
  1603. Marshal.dump(@object)
  1604. true
  1605. end
  1606. transitions.perform do
  1607. Marshal.dump(@object)
  1608. true
  1609. end
  1610. end
  1611. end
  1612. def test_should_marshal_during_after_callbacks
  1613. @machine.after_transition {|object, transition| Marshal.dump(object)}
  1614. assert_nothing_raised do
  1615. transitions(:after => false).perform { true }
  1616. transitions.perform { true }
  1617. end
  1618. end
  1619. def test_should_marshal_during_around_callbacks_before_yield
  1620. @machine.around_transition {|object, transition, block| Marshal.dump(object); block.call}
  1621. assert_nothing_raised do
  1622. transitions(:after => false).perform { true }
  1623. transitions.perform { true }
  1624. end
  1625. end
  1626. def test_should_marshal_during_around_callbacks_after_yield
  1627. @machine.around_transition {|object, transition, block| block.call; Marshal.dump(object)}
  1628. assert_nothing_raised do
  1629. transitions(:after => false).perform { true }
  1630. transitions.perform { true }
  1631. end
  1632. end
  1633. def teardown
  1634. self.class.send(:remove_const, 'Example')
  1635. end
  1636. private
  1637. def transitions(options = {})
  1638. StateMachine::AttributeTransitionCollection.new([
  1639. StateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling)
  1640. ], options)
  1641. end
  1642. end