PageRenderTime 65ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/plugins/state_machine/test/unit/machine_test.rb

https://bitbucket.org/systech3/boxyroom
Ruby | 2004 lines | 1595 code | 407 blank | 2 comment | 9 complexity | a732592fc50b90b38670e800e8b092b3 MD5 | raw file
Possible License(s): JSON, MIT

Large files files are truncated, but you can click here to view the full file

  1. require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
  2. class MachineByDefaultTest < Test::Unit::TestCase
  3. def setup
  4. @klass = Class.new
  5. @machine = StateMachine::Machine.new(@klass)
  6. @object = @klass.new
  7. end
  8. def test_should_have_an_owner_class
  9. assert_equal @klass, @machine.owner_class
  10. end
  11. def test_should_have_a_name
  12. assert_equal :state, @machine.name
  13. end
  14. def test_should_have_an_attribute
  15. assert_equal :state, @machine.attribute
  16. end
  17. def test_should_prefix_custom_attributes_with_attribute
  18. assert_equal :state_event, @machine.attribute(:event)
  19. end
  20. def test_should_have_an_initial_state
  21. assert_not_nil @machine.initial_state(@object)
  22. end
  23. def test_should_have_a_nil_initial_state
  24. assert_nil @machine.initial_state(@object).value
  25. end
  26. def test_should_not_have_any_events
  27. assert !@machine.events.any?
  28. end
  29. def test_should_not_have_any_before_callbacks
  30. assert @machine.callbacks[:before].empty?
  31. end
  32. def test_should_not_have_any_after_callbacks
  33. assert @machine.callbacks[:after].empty?
  34. end
  35. def test_should_not_have_an_action
  36. assert_nil @machine.action
  37. end
  38. def test_should_use_tranactions
  39. assert_equal true, @machine.use_transactions
  40. end
  41. def test_should_not_have_a_namespace
  42. assert_nil @machine.namespace
  43. end
  44. def test_should_have_a_nil_state
  45. assert_equal [nil], @machine.states.keys
  46. end
  47. def test_should_set_initial_on_nil_state
  48. assert @machine.state(nil).initial
  49. end
  50. def test_should_generate_default_messages
  51. assert_equal 'is invalid', @machine.generate_message(:invalid)
  52. assert_equal 'cannot transition when parked', @machine.generate_message(:invalid_event, [[:state, :parked]])
  53. assert_equal 'cannot transition via "park"', @machine.generate_message(:invalid_transition, [[:event, :park]])
  54. end
  55. def test_should_not_be_extended_by_the_active_record_integration
  56. assert !(class << @machine; ancestors; end).include?(StateMachine::Integrations::ActiveRecord)
  57. end
  58. def test_should_not_be_extended_by_the_datamapper_integration
  59. assert !(class << @machine; ancestors; end).include?(StateMachine::Integrations::DataMapper)
  60. end
  61. def test_should_not_be_extended_by_the_sequel_integration
  62. assert !(class << @machine; ancestors; end).include?(StateMachine::Integrations::Sequel)
  63. end
  64. def test_should_define_a_reader_attribute_for_the_attribute
  65. assert @object.respond_to?(:state)
  66. end
  67. def test_should_define_a_writer_attribute_for_the_attribute
  68. assert @object.respond_to?(:state=)
  69. end
  70. def test_should_define_a_predicate_for_the_attribute
  71. assert @object.respond_to?(:state?)
  72. end
  73. def test_should_define_a_name_reader_for_the_attribute
  74. assert @object.respond_to?(:state_name)
  75. end
  76. def test_should_define_an_event_reader_for_the_attribute
  77. assert @object.respond_to?(:state_events)
  78. end
  79. def test_should_define_a_transition_reader_for_the_attribute
  80. assert @object.respond_to?(:state_transitions)
  81. end
  82. def test_should_not_define_an_event_attribute_reader
  83. assert !@object.respond_to?(:state_event)
  84. end
  85. def test_should_not_define_an_event_attribute_writer
  86. assert !@object.respond_to?(:state_event=)
  87. end
  88. def test_should_not_define_an_event_transition_attribute_reader
  89. assert !@object.respond_to?(:state_event_transition)
  90. end
  91. def test_should_not_define_an_event_transition_attribute_writer
  92. assert !@object.respond_to?(:state_event_transition=)
  93. end
  94. def test_should_not_define_singular_with_scope
  95. assert !@klass.respond_to?(:with_state)
  96. end
  97. def test_should_not_define_singular_without_scope
  98. assert !@klass.respond_to?(:without_state)
  99. end
  100. def test_should_not_define_plural_with_scope
  101. assert !@klass.respond_to?(:with_states)
  102. end
  103. def test_should_not_define_plural_without_scope
  104. assert !@klass.respond_to?(:without_states)
  105. end
  106. def test_should_extend_owner_class_with_class_methods
  107. assert (class << @klass; ancestors; end).include?(StateMachine::ClassMethods)
  108. end
  109. def test_should_include_instance_methods_in_owner_class
  110. assert @klass.included_modules.include?(StateMachine::InstanceMethods)
  111. end
  112. def test_should_define_state_machines_reader
  113. expected = {:state => @machine}
  114. assert_equal expected, @klass.state_machines
  115. end
  116. end
  117. class MachineWithCustomNameTest < Test::Unit::TestCase
  118. def setup
  119. @klass = Class.new
  120. @machine = StateMachine::Machine.new(@klass, :status)
  121. @object = @klass.new
  122. end
  123. def test_should_use_custom_name
  124. assert_equal :status, @machine.name
  125. end
  126. def test_should_use_custom_name_for_attribute
  127. assert_equal :status, @machine.attribute
  128. end
  129. def test_should_prefix_custom_attributes_with_custom_name
  130. assert_equal :status_event, @machine.attribute(:event)
  131. end
  132. def test_should_define_a_reader_attribute_for_the_attribute
  133. assert @object.respond_to?(:status)
  134. end
  135. def test_should_define_a_writer_attribute_for_the_attribute
  136. assert @object.respond_to?(:status=)
  137. end
  138. def test_should_define_a_predicate_for_the_attribute
  139. assert @object.respond_to?(:status?)
  140. end
  141. def test_should_define_a_name_reader_for_the_attribute
  142. assert @object.respond_to?(:status_name)
  143. end
  144. def test_should_define_an_event_reader_for_the_attribute
  145. assert @object.respond_to?(:status_events)
  146. end
  147. def test_should_define_a_transition_reader_for_the_attribute
  148. assert @object.respond_to?(:status_transitions)
  149. end
  150. end
  151. class MachineWithStaticInitialStateTest < Test::Unit::TestCase
  152. def setup
  153. @klass = Class.new do
  154. def initialize(attributes = {})
  155. attributes.each {|attr, value| send("#{attr}=", value)}
  156. super()
  157. end
  158. end
  159. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  160. end
  161. def test_should_not_have_dynamic_initial_state
  162. assert !@machine.dynamic_initial_state?
  163. end
  164. def test_should_have_an_initial_state
  165. object = @klass.new
  166. assert_equal 'parked', @machine.initial_state(object).value
  167. end
  168. def test_should_set_initial_on_state_object
  169. assert @machine.state(:parked).initial
  170. end
  171. def test_should_set_initial_state_if_existing_is_nil
  172. object = @klass.new(:state => nil)
  173. assert_equal 'parked', object.state
  174. end
  175. def test_should_set_initial_state_if_existing_is_empty
  176. object = @klass.new(:state => '')
  177. assert_equal 'parked', object.state
  178. end
  179. def test_should_not_set_initial_state_if_existing_is_not_empty
  180. object = @klass.new(:state => 'idling')
  181. assert_equal 'idling', object.state
  182. end
  183. def test_should_set_initial_state_prior_to_initialization
  184. base = Class.new do
  185. attr_accessor :state_on_init
  186. def initialize
  187. self.state_on_init = state
  188. end
  189. end
  190. klass = Class.new(base)
  191. machine = StateMachine::Machine.new(klass, :initial => :parked)
  192. assert_equal 'parked', klass.new.state_on_init
  193. end
  194. def test_should_be_included_in_known_states
  195. assert_equal [:parked], @machine.states.keys
  196. end
  197. end
  198. class MachineWithDynamicInitialStateTest < Test::Unit::TestCase
  199. def setup
  200. @klass = Class.new do
  201. attr_accessor :initial_state
  202. end
  203. @machine = StateMachine::Machine.new(@klass, :initial => lambda {|object| object.initial_state || :default})
  204. @machine.state :parked, :idling, :default
  205. @object = @klass.new
  206. end
  207. def test_should_have_dynamic_initial_state
  208. assert @machine.dynamic_initial_state?
  209. end
  210. def test_should_use_the_record_for_determining_the_initial_state
  211. @object.initial_state = :parked
  212. assert_equal :parked, @machine.initial_state(@object).name
  213. @object.initial_state = :idling
  214. assert_equal :idling, @machine.initial_state(@object).name
  215. end
  216. def test_should_set_initial_state_on_created_object
  217. assert_equal 'default', @object.state
  218. end
  219. def test_should_set_initial_state_after_initialization
  220. base = Class.new do
  221. attr_accessor :state_on_init
  222. def initialize
  223. self.state_on_init = state
  224. end
  225. end
  226. klass = Class.new(base)
  227. machine = StateMachine::Machine.new(klass, :initial => lambda {|object| :parked})
  228. machine.state :parked
  229. assert_nil klass.new.state_on_init
  230. end
  231. def test_should_not_be_included_in_known_states
  232. assert_equal [:parked, :idling, :default], @machine.states.map {|state| state.name}
  233. end
  234. end
  235. class MachineWithCustomActionTest < Test::Unit::TestCase
  236. def setup
  237. @machine = StateMachine::Machine.new(Class.new, :action => :save)
  238. end
  239. def test_should_use_the_custom_action
  240. assert_equal :save, @machine.action
  241. end
  242. end
  243. class MachineWithNilActionTest < Test::Unit::TestCase
  244. def setup
  245. integration = Module.new do
  246. class << self; attr_reader :defaults; end
  247. @defaults = {:action => :save}
  248. end
  249. StateMachine::Integrations.const_set('Custom', integration)
  250. @machine = StateMachine::Machine.new(Class.new, :action => nil, :integration => :custom)
  251. end
  252. def test_should_have_a_nil_action
  253. assert_nil @machine.action
  254. end
  255. def teardown
  256. StateMachine::Integrations.send(:remove_const, 'Custom')
  257. end
  258. end
  259. class MachineWithoutIntegrationTest < Test::Unit::TestCase
  260. def setup
  261. @klass = Class.new
  262. @machine = StateMachine::Machine.new(@klass)
  263. @object = @klass.new
  264. end
  265. def test_transaction_should_yield
  266. @yielded = false
  267. @machine.within_transaction(@object) do
  268. @yielded = true
  269. end
  270. assert @yielded
  271. end
  272. def test_invalidation_should_do_nothing
  273. assert_nil @machine.invalidate(@object, :state, :invalid_transition, [[:event, :park]])
  274. end
  275. def test_reset_should_do_nothing
  276. assert_nil @machine.reset(@object)
  277. end
  278. end
  279. class MachineWithCustomIntegrationTest < Test::Unit::TestCase
  280. def setup
  281. StateMachine::Integrations.const_set('Custom', Module.new)
  282. @machine = StateMachine::Machine.new(Class.new, :integration => :custom)
  283. end
  284. def test_should_be_extended_by_the_integration
  285. assert (class << @machine; ancestors; end).include?(StateMachine::Integrations::Custom)
  286. end
  287. def teardown
  288. StateMachine::Integrations.send(:remove_const, 'Custom')
  289. end
  290. end
  291. class MachineWithIntegrationTest < Test::Unit::TestCase
  292. def setup
  293. StateMachine::Integrations.const_set('Custom', Module.new do
  294. class << self; attr_reader :defaults; end
  295. @defaults = {:action => :save, :use_transactions => false}
  296. attr_reader :initialized, :with_scopes, :without_scopes, :ran_transaction
  297. def after_initialize
  298. @initialized = true
  299. end
  300. def create_with_scope(name)
  301. (@with_scopes ||= []) << name
  302. lambda {}
  303. end
  304. def create_without_scope(name)
  305. (@without_scopes ||= []) << name
  306. lambda {}
  307. end
  308. def transaction(object)
  309. @ran_transaction = true
  310. yield
  311. end
  312. end)
  313. @machine = StateMachine::Machine.new(Class.new, :integration => :custom)
  314. end
  315. def test_should_call_after_initialize_hook
  316. assert @machine.initialized
  317. end
  318. def test_should_use_the_default_action
  319. assert_equal :save, @machine.action
  320. end
  321. def test_should_use_the_custom_action_if_specified
  322. machine = StateMachine::Machine.new(Class.new, :integration => :custom, :action => :save!)
  323. assert_equal :save!, machine.action
  324. end
  325. def test_should_use_the_default_use_transactions
  326. assert_equal false, @machine.use_transactions
  327. end
  328. def test_should_use_the_custom_use_transactions_if_specified
  329. machine = StateMachine::Machine.new(Class.new, :integration => :custom, :use_transactions => true)
  330. assert_equal true, machine.use_transactions
  331. end
  332. def test_should_define_a_singular_and_plural_with_scope
  333. assert_equal %w(with_state with_states), @machine.with_scopes
  334. end
  335. def test_should_define_a_singular_and_plural_without_scope
  336. assert_equal %w(without_state without_states), @machine.without_scopes
  337. end
  338. def teardown
  339. StateMachine::Integrations.send(:remove_const, 'Custom')
  340. end
  341. end
  342. class MachineWithActionTest < Test::Unit::TestCase
  343. def setup
  344. @klass = Class.new do
  345. def save
  346. end
  347. end
  348. @machine = StateMachine::Machine.new(@klass, :action => :save)
  349. @object = @klass.new
  350. end
  351. def test_should_define_an_event_attribute_reader
  352. assert @object.respond_to?(:state_event)
  353. end
  354. def test_should_define_an_event_attribute_writer
  355. assert @object.respond_to?(:state_event=)
  356. end
  357. def test_should_define_an_event_transition_attribute_reader
  358. assert @object.respond_to?(:state_event_transition)
  359. end
  360. def test_should_define_an_event_transition_attribute_writer
  361. assert @object.respond_to?(:state_event_transition=)
  362. end
  363. end
  364. class MachineWithActionUndefinedTest < Test::Unit::TestCase
  365. def setup
  366. @klass = Class.new
  367. @machine = StateMachine::Machine.new(@klass, :action => :save)
  368. @object = @klass.new
  369. end
  370. def test_should_define_an_event_attribute_reader
  371. assert @object.respond_to?(:state_event)
  372. end
  373. def test_should_define_an_event_attribute_writer
  374. assert @object.respond_to?(:state_event=)
  375. end
  376. def test_should_define_an_event_transition_attribute_reader
  377. assert @object.respond_to?(:state_event_transition)
  378. end
  379. def test_should_define_an_event_transition_attribute_writer
  380. assert @object.respond_to?(:state_event_transition=)
  381. end
  382. def test_should_not_define_action
  383. assert !@object.respond_to?(:save)
  384. end
  385. end
  386. class MachineWithCustomPluralTest < Test::Unit::TestCase
  387. def setup
  388. @integration = Module.new do
  389. class << self; attr_accessor :with_scopes, :without_scopes; end
  390. @with_scopes = []
  391. @without_scopes = []
  392. def create_with_scope(name)
  393. StateMachine::Integrations::Custom.with_scopes << name
  394. lambda {}
  395. end
  396. def create_without_scope(name)
  397. StateMachine::Integrations::Custom.without_scopes << name
  398. lambda {}
  399. end
  400. end
  401. StateMachine::Integrations.const_set('Custom', @integration)
  402. @machine = StateMachine::Machine.new(Class.new, :integration => :custom, :plural => 'staties')
  403. end
  404. def test_should_define_a_singular_and_plural_with_scope
  405. assert_equal %w(with_state with_staties), @integration.with_scopes
  406. end
  407. def test_should_define_a_singular_and_plural_without_scope
  408. assert_equal %w(without_state without_staties), @integration.without_scopes
  409. end
  410. def teardown
  411. StateMachine::Integrations.send(:remove_const, 'Custom')
  412. end
  413. end
  414. class MachineWithCustomInvalidationTest < Test::Unit::TestCase
  415. def setup
  416. @integration = Module.new do
  417. def invalidate(object, attribute, message, values = [])
  418. object.error = generate_message(message, values)
  419. end
  420. end
  421. StateMachine::Integrations.const_set('Custom', @integration)
  422. @klass = Class.new do
  423. attr_accessor :error
  424. end
  425. @machine = StateMachine::Machine.new(@klass, :integration => :custom, :messages => {:invalid_transition => 'cannot %s'})
  426. @machine.state :parked
  427. @object = @klass.new
  428. @object.state = 'parked'
  429. end
  430. def test_generate_custom_message
  431. assert_equal 'cannot park', @machine.generate_message(:invalid_transition, [[:event, :park]])
  432. end
  433. def test_use_custom_message
  434. @machine.invalidate(@object, :state, :invalid_transition, [[:event, :park]])
  435. assert_equal 'cannot park', @object.error
  436. end
  437. def teardown
  438. StateMachine::Integrations.send(:remove_const, 'Custom')
  439. end
  440. end
  441. class MachineTest < Test::Unit::TestCase
  442. def test_should_raise_exception_if_invalid_option_specified
  443. assert_raise(ArgumentError) {StateMachine::Machine.new(Class.new, :invalid => true)}
  444. end
  445. def test_should_not_raise_exception_if_custom_messages_specified
  446. assert_nothing_raised {StateMachine::Machine.new(Class.new, :messages => {:invalid_transition => 'custom'})}
  447. end
  448. def test_should_evaluate_a_block_during_initialization
  449. called = true
  450. StateMachine::Machine.new(Class.new) do
  451. called = respond_to?(:event)
  452. end
  453. assert called
  454. end
  455. def test_should_provide_matcher_helpers_during_initialization
  456. matchers = []
  457. StateMachine::Machine.new(Class.new) do
  458. matchers = [all, any, same]
  459. end
  460. assert_equal [StateMachine::AllMatcher.instance, StateMachine::AllMatcher.instance, StateMachine::LoopbackMatcher.instance], matchers
  461. end
  462. end
  463. class MachineAfterBeingCopiedTest < Test::Unit::TestCase
  464. def setup
  465. @machine = StateMachine::Machine.new(Class.new, :state, :initial => :parked)
  466. @machine.event(:ignite) {}
  467. @machine.before_transition(lambda {})
  468. @machine.after_transition(lambda {})
  469. @copied_machine = @machine.clone
  470. end
  471. def test_should_not_have_the_same_collection_of_states
  472. assert_not_same @copied_machine.states, @machine.states
  473. end
  474. def test_should_copy_each_state
  475. assert_not_same @copied_machine.states[:parked], @machine.states[:parked]
  476. end
  477. def test_should_update_machine_for_each_state
  478. assert_equal @copied_machine, @copied_machine.states[:parked].machine
  479. end
  480. def test_should_not_update_machine_for_original_state
  481. assert_equal @machine, @machine.states[:parked].machine
  482. end
  483. def test_should_not_have_the_same_collection_of_events
  484. assert_not_same @copied_machine.events, @machine.events
  485. end
  486. def test_should_copy_each_event
  487. assert_not_same @copied_machine.events[:ignite], @machine.events[:ignite]
  488. end
  489. def test_should_update_machine_for_each_event
  490. assert_equal @copied_machine, @copied_machine.events[:ignite].machine
  491. end
  492. def test_should_not_update_machine_for_original_event
  493. assert_equal @machine, @machine.events[:ignite].machine
  494. end
  495. def test_should_not_have_the_same_callbacks
  496. assert_not_same @copied_machine.callbacks, @machine.callbacks
  497. end
  498. def test_should_not_have_the_same_before_callbacks
  499. assert_not_same @copied_machine.callbacks[:before], @machine.callbacks[:before]
  500. end
  501. def test_should_not_have_the_same_after_callbacks
  502. assert_not_same @copied_machine.callbacks[:after], @machine.callbacks[:after]
  503. end
  504. end
  505. class MachineAfterChangingOwnerClassTest < Test::Unit::TestCase
  506. def setup
  507. @original_class = Class.new
  508. @machine = StateMachine::Machine.new(@original_class)
  509. @new_class = Class.new(@original_class)
  510. @new_machine = @machine.clone
  511. @new_machine.owner_class = @new_class
  512. @object = @new_class.new
  513. end
  514. def test_should_update_owner_class
  515. assert_equal @new_class, @new_machine.owner_class
  516. end
  517. def test_should_not_change_original_owner_class
  518. assert_equal @original_class, @machine.owner_class
  519. end
  520. def test_should_change_the_associated_machine_in_the_new_class
  521. assert_equal @new_machine, @new_class.state_machines[:state]
  522. end
  523. def test_should_not_change_the_associated_machine_in_the_original_class
  524. assert_equal @machine, @original_class.state_machines[:state]
  525. end
  526. end
  527. class MachineAfterChangingInitialState < Test::Unit::TestCase
  528. def setup
  529. @klass = Class.new
  530. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  531. @machine.initial_state = :idling
  532. @object = @klass.new
  533. end
  534. def test_should_change_the_initial_state
  535. assert_equal :idling, @machine.initial_state(@object).name
  536. end
  537. def test_should_include_in_known_states
  538. assert_equal [:parked, :idling], @machine.states.map {|state| state.name}
  539. end
  540. def test_should_reset_original_initial_state
  541. assert !@machine.state(:parked).initial
  542. end
  543. def test_should_set_new_state_to_initial
  544. assert @machine.state(:idling).initial
  545. end
  546. end
  547. class MachineWithInstanceHelpersTest < Test::Unit::TestCase
  548. def setup
  549. @klass = Class.new
  550. @machine = StateMachine::Machine.new(@klass)
  551. @object = @klass.new
  552. end
  553. def test_should_not_redefine_existing_public_methods
  554. @klass.class_eval do
  555. def state
  556. 'parked'
  557. end
  558. end
  559. @machine.define_instance_method(:state) {}
  560. assert_equal 'parked', @object.state
  561. end
  562. def test_should_not_redefine_existing_protected_methods
  563. @klass.class_eval do
  564. protected
  565. def state
  566. 'parked'
  567. end
  568. end
  569. @machine.define_instance_method(:state) {}
  570. assert_equal 'parked', @object.send(:state)
  571. end
  572. def test_should_not_redefine_existing_private_methods
  573. @klass.class_eval do
  574. private
  575. def state
  576. 'parked'
  577. end
  578. end
  579. @machine.define_instance_method(:state) {}
  580. assert_equal 'parked', @object.send(:state)
  581. end
  582. def test_should_define_nonexistent_methods
  583. @machine.define_instance_method(:state) {'parked'}
  584. assert_equal 'parked', @object.state
  585. end
  586. end
  587. class MachineWithClassHelpersTest < Test::Unit::TestCase
  588. def setup
  589. @klass = Class.new
  590. @machine = StateMachine::Machine.new(@klass)
  591. end
  592. def test_should_not_redefine_existing_public_methods
  593. class << @klass
  594. def states
  595. []
  596. end
  597. end
  598. @machine.define_class_method(:states) {}
  599. assert_equal [], @klass.states
  600. end
  601. def test_should_not_redefine_existing_protected_methods
  602. class << @klass
  603. protected
  604. def states
  605. []
  606. end
  607. end
  608. @machine.define_class_method(:states) {}
  609. assert_equal [], @klass.send(:states)
  610. end
  611. def test_should_not_redefine_existing_private_methods
  612. class << @klass
  613. private
  614. def states
  615. []
  616. end
  617. end
  618. @machine.define_class_method(:states) {}
  619. assert_equal [], @klass.send(:states)
  620. end
  621. def test_should_define_nonexistent_methods
  622. @machine.define_class_method(:states) {[]}
  623. assert_equal [], @klass.states
  624. end
  625. end
  626. class MachineWithConflictingHelpersTest < Test::Unit::TestCase
  627. def setup
  628. @klass = Class.new do
  629. def self.with_state
  630. :with_state
  631. end
  632. def self.with_states
  633. :with_states
  634. end
  635. def self.without_state
  636. :without_state
  637. end
  638. def self.without_states
  639. :without_states
  640. end
  641. attr_accessor :status
  642. def state
  643. 'parked'
  644. end
  645. def state=(value)
  646. self.status = value
  647. end
  648. def state?
  649. true
  650. end
  651. def state_name
  652. :parked
  653. end
  654. def state_events
  655. [:ignite]
  656. end
  657. def state_transitions
  658. [{:parked => :idling}]
  659. end
  660. end
  661. StateMachine::Integrations.const_set('Custom', Module.new do
  662. def create_with_scope(name)
  663. lambda {|klass, values| []}
  664. end
  665. def create_without_scope(name)
  666. lambda {|klass, values| []}
  667. end
  668. end)
  669. @machine = StateMachine::Machine.new(@klass, :integration => :custom)
  670. @machine.state :parked, :idling
  671. @object = @klass.new
  672. end
  673. def test_should_not_redefine_singular_with_scope
  674. assert_equal :with_state, @klass.with_state
  675. end
  676. def test_should_not_redefine_plural_with_scope
  677. assert_equal :with_states, @klass.with_states
  678. end
  679. def test_should_not_redefine_singular_without_scope
  680. assert_equal :without_state, @klass.without_state
  681. end
  682. def test_should_not_redefine_plural_without_scope
  683. assert_equal :without_states, @klass.without_states
  684. end
  685. def test_should_not_redefine_attribute_writer
  686. assert_equal 'parked', @object.state
  687. end
  688. def test_should_not_redefine_attribute_writer
  689. @object.state = 'parked'
  690. assert_equal 'parked', @object.status
  691. end
  692. def test_should_not_define_attribute_predicate
  693. assert @object.state?
  694. end
  695. def test_should_not_redefine_attribute_name_reader
  696. assert_equal :parked, @object.state_name
  697. end
  698. def test_should_not_redefine_attribute_events_reader
  699. assert_equal [:ignite], @object.state_events
  700. end
  701. def test_should_not_redefine_attribute_transitions_reader
  702. assert_equal [{:parked => :idling}], @object.state_transitions
  703. end
  704. def test_should_allow_super_chaining
  705. @klass.class_eval do
  706. def self.with_state(*states)
  707. super == []
  708. end
  709. def self.with_states(*states)
  710. super == []
  711. end
  712. def self.without_state(*states)
  713. super == []
  714. end
  715. def self.without_states(*states)
  716. super == []
  717. end
  718. attr_accessor :status
  719. def state
  720. super || 'parked'
  721. end
  722. def state=(value)
  723. super
  724. self.status = value
  725. end
  726. def state?(state)
  727. super ? 1 : 0
  728. end
  729. def state_name
  730. super == :parked ? 1 : 0
  731. end
  732. def state_events
  733. super == []
  734. end
  735. def state_transitions
  736. super == []
  737. end
  738. end
  739. assert_equal true, @klass.with_state
  740. assert_equal true, @klass.with_states
  741. assert_equal true, @klass.without_state
  742. assert_equal true, @klass.without_states
  743. assert_equal 'parked', @object.state
  744. @object.state = 'idling'
  745. assert_equal 'idling', @object.status
  746. assert_equal 0, @object.state?(:parked)
  747. assert_equal 0, @object.state_name
  748. assert_equal true, @object.state_events
  749. assert_equal true, @object.state_transitions
  750. end
  751. def teardown
  752. StateMachine::Integrations.send(:remove_const, 'Custom')
  753. end
  754. end
  755. class MachineWithoutInitializeTest < Test::Unit::TestCase
  756. def setup
  757. @klass = Class.new
  758. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  759. @object = @klass.new
  760. end
  761. def test_should_initialize_state
  762. assert_equal 'parked', @object.state
  763. end
  764. end
  765. class MachineWithInitializeWithoutSuperTest < Test::Unit::TestCase
  766. def setup
  767. @klass = Class.new do
  768. def initialize
  769. end
  770. end
  771. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  772. @object = @klass.new
  773. end
  774. def test_should_not_initialize_state
  775. assert_nil @object.state
  776. end
  777. end
  778. class MachineWithInitializeAndSuperTest < Test::Unit::TestCase
  779. def setup
  780. @klass = Class.new do
  781. def initialize
  782. super()
  783. end
  784. end
  785. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  786. @object = @klass.new
  787. end
  788. def test_should_initialize_state
  789. assert_equal 'parked', @object.state
  790. end
  791. end
  792. class MachineWithInitializeArgumentsAndBlockTest < Test::Unit::TestCase
  793. def setup
  794. @superclass = Class.new do
  795. attr_reader :args
  796. attr_reader :block_given
  797. def initialize(*args)
  798. @args = args
  799. @block_given = block_given?
  800. end
  801. end
  802. @klass = Class.new(@superclass)
  803. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  804. @object = @klass.new(1, 2, 3) {}
  805. end
  806. def test_should_initialize_state
  807. assert_equal 'parked', @object.state
  808. end
  809. def test_should_preserve_arguments
  810. assert_equal [1, 2, 3], @object.args
  811. end
  812. def test_should_preserve_block
  813. assert @object.block_given
  814. end
  815. end
  816. class MachineWithCustomInitializeTest < Test::Unit::TestCase
  817. def setup
  818. @klass = Class.new do
  819. def initialize
  820. initialize_state_machines
  821. end
  822. end
  823. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  824. @object = @klass.new
  825. end
  826. def test_should_initialize_state
  827. assert_equal 'parked', @object.state
  828. end
  829. end
  830. class MachinePersistenceTest < Test::Unit::TestCase
  831. def setup
  832. @klass = Class.new do
  833. attr_accessor :state_event
  834. end
  835. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  836. @object = @klass.new
  837. end
  838. def test_should_allow_reading_state
  839. assert_equal 'parked', @machine.read(@object, :state)
  840. end
  841. def test_should_allow_reading_custom_attributes
  842. assert_nil @machine.read(@object, :event)
  843. @object.state_event = 'ignite'
  844. assert_equal 'ignite', @machine.read(@object, :event)
  845. end
  846. def test_should_allow_reading_custom_instance_variables
  847. @klass.class_eval do
  848. attr_writer :state_value
  849. end
  850. @object.state_value = 1
  851. assert_raise(NoMethodError) { @machine.read(@object, :value) }
  852. assert_equal 1, @machine.read(@object, :value, true)
  853. end
  854. def test_should_allow_writing_state
  855. @machine.write(@object, :state, 'idling')
  856. assert_equal 'idling', @object.state
  857. end
  858. def test_should_allow_writing_custom_attributes
  859. @machine.write(@object, :event, 'ignite')
  860. assert_equal 'ignite', @object.state_event
  861. end
  862. end
  863. class MachineWithStatesTest < Test::Unit::TestCase
  864. def setup
  865. @klass = Class.new
  866. @machine = StateMachine::Machine.new(@klass)
  867. @parked, @idling = @machine.state :parked, :idling
  868. @object = @klass.new
  869. end
  870. def test_should_have_states
  871. assert_equal [nil, :parked, :idling], @machine.states.map {|state| state.name}
  872. end
  873. def test_should_allow_state_lookup_by_name
  874. assert_equal @parked, @machine.states[:parked]
  875. end
  876. def test_should_allow_state_lookup_by_value
  877. assert_equal @parked, @machine.states['parked', :value]
  878. end
  879. def test_should_use_stringified_name_for_value
  880. assert_equal 'parked', @parked.value
  881. end
  882. def test_should_not_use_custom_matcher
  883. assert_nil @parked.matcher
  884. end
  885. def test_should_raise_exception_if_invalid_option_specified
  886. exception = assert_raise(ArgumentError) {@machine.state(:first_gear, :invalid => true)}
  887. assert_equal 'Invalid key(s): invalid', exception.message
  888. end
  889. end
  890. class MachineWithStatesWithCustomValuesTest < Test::Unit::TestCase
  891. def setup
  892. @klass = Class.new
  893. @machine = StateMachine::Machine.new(@klass)
  894. @state = @machine.state :parked, :value => 1
  895. @object = @klass.new
  896. @object.state = 1
  897. end
  898. def test_should_use_custom_value
  899. assert_equal 1, @state.value
  900. end
  901. def test_should_allow_lookup_by_custom_value
  902. assert_equal @state, @machine.states[1, :value]
  903. end
  904. end
  905. class MachineWithStatesWithRuntimeDependenciesTest < Test::Unit::TestCase
  906. def setup
  907. @klass = Class.new
  908. @machine = StateMachine::Machine.new(@klass)
  909. @machine.state :parked
  910. end
  911. def test_should_not_evaluate_value_during_definition
  912. assert_nothing_raised { @machine.state :parked, :value => lambda {raise ArgumentError} }
  913. end
  914. def test_should_not_evaluate_if_not_initial_state
  915. @machine.state :parked, :value => lambda {raise ArgumentError}
  916. assert_nothing_raised { @klass.new }
  917. end
  918. end
  919. class MachineWithStateWithMatchersTest < Test::Unit::TestCase
  920. def setup
  921. @klass = Class.new
  922. @machine = StateMachine::Machine.new(@klass)
  923. @state = @machine.state :parked, :if => lambda {|value| !value.nil?}
  924. @object = @klass.new
  925. @object.state = 1
  926. end
  927. def test_should_use_custom_matcher
  928. assert_not_nil @state.matcher
  929. assert @state.matches?(1)
  930. assert !@state.matches?(nil)
  931. end
  932. end
  933. class MachineWithCachedStateTest < Test::Unit::TestCase
  934. def setup
  935. @klass = Class.new
  936. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  937. @state = @machine.state :parked, :value => lambda {Object.new}, :cache => true
  938. @object = @klass.new
  939. end
  940. def test_should_use_evaluated_value
  941. assert_instance_of Object, @object.state
  942. end
  943. def test_use_same_value_across_multiple_objects
  944. assert_equal @object.state, @klass.new.state
  945. end
  946. end
  947. class MachineWithStatesWithBehaviorsTest < Test::Unit::TestCase
  948. def setup
  949. @klass = Class.new
  950. @machine = StateMachine::Machine.new(@klass)
  951. @parked, @idling = @machine.state :parked, :idling do
  952. def speed
  953. 0
  954. end
  955. end
  956. end
  957. def test_should_define_behaviors_for_each_state
  958. assert_not_nil @parked.methods[:speed]
  959. assert_not_nil @idling.methods[:speed]
  960. end
  961. def test_should_define_different_behaviors_for_each_state
  962. assert_not_equal @parked.methods[:speed], @idling.methods[:speed]
  963. end
  964. end
  965. class MachineWithExistingStateTest < Test::Unit::TestCase
  966. def setup
  967. @klass = Class.new
  968. @machine = StateMachine::Machine.new(@klass)
  969. @state = @machine.state :parked
  970. @same_state = @machine.state :parked, :value => 1
  971. end
  972. def test_should_not_create_a_new_state
  973. assert_same @state, @same_state
  974. end
  975. def test_should_update_attributes
  976. assert_equal 1, @state.value
  977. end
  978. def test_should_no_longer_be_able_to_look_up_state_by_original_value
  979. assert_nil @machine.states['parked', :value]
  980. end
  981. def test_should_be_able_to_look_up_state_by_new_value
  982. assert_equal @state, @machine.states[1, :value]
  983. end
  984. end
  985. class MachineWithOtherStates < Test::Unit::TestCase
  986. def setup
  987. @klass = Class.new
  988. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  989. @parked, @idling = @machine.other_states(:parked, :idling)
  990. end
  991. def test_should_include_other_states_in_known_states
  992. assert_equal [@parked, @idling], @machine.states.to_a
  993. end
  994. def test_should_use_default_value
  995. assert_equal 'idling', @idling.value
  996. end
  997. def test_should_not_create_matcher
  998. assert_nil @idling.matcher
  999. end
  1000. end
  1001. class MachineWithEventsTest < Test::Unit::TestCase
  1002. def setup
  1003. @klass = Class.new
  1004. @machine = StateMachine::Machine.new(@klass)
  1005. end
  1006. def test_should_return_the_created_event
  1007. assert_instance_of StateMachine::Event, @machine.event(:ignite)
  1008. end
  1009. def test_should_create_event_with_given_name
  1010. event = @machine.event(:ignite) {}
  1011. assert_equal :ignite, event.name
  1012. end
  1013. def test_should_evaluate_block_within_event_context
  1014. responded = false
  1015. @machine.event :ignite do
  1016. responded = respond_to?(:transition)
  1017. end
  1018. assert responded
  1019. end
  1020. def test_should_be_aliased_as_on
  1021. event = @machine.on(:ignite) {}
  1022. assert_equal :ignite, event.name
  1023. end
  1024. def test_should_have_events
  1025. event = @machine.event(:ignite)
  1026. assert_equal [event], @machine.events.to_a
  1027. end
  1028. end
  1029. class MachineWithExistingEventTest < Test::Unit::TestCase
  1030. def setup
  1031. @machine = StateMachine::Machine.new(Class.new)
  1032. @event = @machine.event(:ignite)
  1033. @same_event = @machine.event(:ignite)
  1034. end
  1035. def test_should_not_create_new_event
  1036. assert_same @event, @same_event
  1037. end
  1038. def test_should_allow_accessing_event_without_block
  1039. assert_equal @event, @machine.event(:ignite)
  1040. end
  1041. end
  1042. class MachineWithEventsWithTransitionsTest < Test::Unit::TestCase
  1043. def setup
  1044. @klass = Class.new
  1045. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  1046. @event = @machine.event(:ignite) do
  1047. transition :parked => :idling
  1048. transition :stalled => :idling
  1049. end
  1050. end
  1051. def test_should_have_events
  1052. assert_equal [@event], @machine.events.to_a
  1053. end
  1054. def test_should_track_states_defined_in_event_transitions
  1055. assert_equal [:parked, :idling, :stalled], @machine.states.map {|state| state.name}
  1056. end
  1057. def test_should_not_duplicate_states_defined_in_multiple_event_transitions
  1058. @machine.event :park do
  1059. transition :idling => :parked
  1060. end
  1061. assert_equal [:parked, :idling, :stalled], @machine.states.map {|state| state.name}
  1062. end
  1063. def test_should_track_state_from_new_events
  1064. @machine.event :shift_up do
  1065. transition :idling => :first_gear
  1066. end
  1067. assert_equal [:parked, :idling, :stalled, :first_gear], @machine.states.map {|state| state.name}
  1068. end
  1069. end
  1070. class MachineWithMultipleEventsTest < Test::Unit::TestCase
  1071. def setup
  1072. @klass = Class.new
  1073. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  1074. @park, @shift_down = @machine.event(:park, :shift_down) do
  1075. transition :first_gear => :parked
  1076. end
  1077. end
  1078. def test_should_have_events
  1079. assert_equal [@park, @shift_down], @machine.events.to_a
  1080. end
  1081. def test_should_define_transitions_for_each_event
  1082. [@park, @shift_down].each {|event| assert_equal 1, event.guards.size}
  1083. end
  1084. def test_should_transition_the_same_for_each_event
  1085. object = @klass.new
  1086. object.state = 'first_gear'
  1087. object.park
  1088. assert_equal 'parked', object.state
  1089. object = @klass.new
  1090. object.state = 'first_gear'
  1091. object.shift_down
  1092. assert_equal 'parked', object.state
  1093. end
  1094. end
  1095. class MachineWithTransitionCallbacksTest < Test::Unit::TestCase
  1096. def setup
  1097. @klass = Class.new do
  1098. attr_accessor :callbacks
  1099. end
  1100. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  1101. @event = @machine.event :ignite do
  1102. transition :parked => :idling
  1103. end
  1104. @object = @klass.new
  1105. @object.callbacks = []
  1106. end
  1107. def test_should_not_raise_exception_if_implicit_option_specified
  1108. assert_nothing_raised {@machine.before_transition :invalid => :valid, :do => lambda {}}
  1109. end
  1110. def test_should_raise_exception_if_method_not_specified
  1111. exception = assert_raise(ArgumentError) {@machine.before_transition :to => :idling}
  1112. assert_equal 'Method(s) for callback must be specified', exception.message
  1113. end
  1114. def test_should_invoke_callbacks_during_transition
  1115. @machine.before_transition lambda {|object| object.callbacks << 'before'}
  1116. @machine.after_transition lambda {|object| object.callbacks << 'after'}
  1117. @event.fire(@object)
  1118. assert_equal %w(before after), @object.callbacks
  1119. end
  1120. def test_should_allow_multiple_callbacks
  1121. @machine.before_transition lambda {|object| object.callbacks << 'before1'}, lambda {|object| object.callbacks << 'before2'}
  1122. @machine.after_transition lambda {|object| object.callbacks << 'after1'}, lambda {|object| object.callbacks << 'after2'}
  1123. @event.fire(@object)
  1124. assert_equal %w(before1 before2 after1 after2), @object.callbacks
  1125. end
  1126. def test_should_allow_multiple_callbacks_with_requirements
  1127. @machine.before_transition lambda {|object| object.callbacks << 'before_parked1'}, lambda {|object| object.callbacks << 'before_parked2'}, :from => :parked
  1128. @machine.before_transition lambda {|object| object.callbacks << 'before_idling1'}, lambda {|object| object.callbacks << 'before_idling2'}, :from => :idling
  1129. @machine.after_transition lambda {|object| object.callbacks << 'after_parked1'}, lambda {|object| object.callbacks << 'after_parked2'}, :from => :parked
  1130. @machine.after_transition lambda {|object| object.callbacks << 'after_idling1'}, lambda {|object| object.callbacks << 'after_idling2'}, :from => :idling
  1131. @event.fire(@object)
  1132. assert_equal %w(before_parked1 before_parked2 after_parked1 after_parked2), @object.callbacks
  1133. end
  1134. def test_should_support_from_requirement
  1135. @machine.before_transition :from => :parked, :do => lambda {|object| object.callbacks << :parked}
  1136. @machine.before_transition :from => :idling, :do => lambda {|object| object.callbacks << :idling}
  1137. @event.fire(@object)
  1138. assert_equal [:parked], @object.callbacks
  1139. end
  1140. def test_should_support_except_from_requirement
  1141. @machine.before_transition :except_from => :parked, :do => lambda {|object| object.callbacks << :parked}
  1142. @machine.before_transition :except_from => :idling, :do => lambda {|object| object.callbacks << :idling}
  1143. @event.fire(@object)
  1144. assert_equal [:idling], @object.callbacks
  1145. end
  1146. def test_should_support_to_requirement
  1147. @machine.before_transition :to => :parked, :do => lambda {|object| object.callbacks << :parked}
  1148. @machine.before_transition :to => :idling, :do => lambda {|object| object.callbacks << :idling}
  1149. @event.fire(@object)
  1150. assert_equal [:idling], @object.callbacks
  1151. end
  1152. def test_should_support_except_to_requirement
  1153. @machine.before_transition :except_to => :parked, :do => lambda {|object| object.callbacks << :parked}
  1154. @machine.before_transition :except_to => :idling, :do => lambda {|object| object.callbacks << :idling}
  1155. @event.fire(@object)
  1156. assert_equal [:parked], @object.callbacks
  1157. end
  1158. def test_should_support_on_requirement
  1159. @machine.before_transition :on => :park, :do => lambda {|object| object.callbacks << :park}
  1160. @machine.before_transition :on => :ignite, :do => lambda {|object| object.callbacks << :ignite}
  1161. @event.fire(@object)
  1162. assert_equal [:ignite], @object.callbacks
  1163. end
  1164. def test_should_support_except_on_requirement
  1165. @machine.before_transition :except_on => :park, :do => lambda {|object| object.callbacks << :park}
  1166. @machine.before_transition :except_on => :ignite, :do => lambda {|object| object.callbacks << :ignite}
  1167. @event.fire(@object)
  1168. assert_equal [:park], @object.callbacks
  1169. end
  1170. def test_should_support_implicit_requirement
  1171. @machine.before_transition :parked => :idling, :do => lambda {|object| object.callbacks << :parked}
  1172. @machine.before_transition :idling => :parked, :do => lambda {|object| object.callbacks << :idling}
  1173. @event.fire(@object)
  1174. assert_equal [:parked], @object.callbacks
  1175. end
  1176. def test_should_track_states_defined_in_transition_callbacks
  1177. @machine.before_transition :parked => :idling, :do => lambda {}
  1178. @machine.after_transition :first_gear => :second_gear, :do => lambda {}
  1179. assert_equal [:parked, :idling, :first_gear, :second_gear], @machine.states.map {|state| state.name}
  1180. end
  1181. def test_should_not_duplicate_states_defined_in_multiple_event_transitions
  1182. @machine.before_transition :parked => :idling, :do => lambda {}
  1183. @machine.after_transition :first_gear => :second_gear, :do => lambda {}
  1184. @machine.after_transition :parked => :idling, :do => lambda {}
  1185. assert_equal [:parked, :idling, :first_gear, :second_gear], @machine.states.map {|state| state.name}
  1186. end
  1187. def test_should_define_predicates_for_each_state
  1188. [:parked?, :idling?].each {|predicate| assert @object.respond_to?(predicate)}
  1189. end
  1190. end
  1191. class MachineWithOwnerSubclassTest < Test::Unit::TestCase
  1192. def setup
  1193. @klass = Class.new
  1194. @machine = StateMachine::Machine.new(@klass)
  1195. @subclass = Class.new(@klass)
  1196. end
  1197. def test_should_have_a_different_collection_of_state_machines
  1198. assert_not_same @klass.state_machines, @subclass.state_machines
  1199. end
  1200. def test_should_have_the_same_attribute_associated_state_machines
  1201. assert_equal @klass.state_machines, @subclass.state_machines
  1202. end
  1203. end
  1204. class MachineWithExistingMachinesOnOwnerClassTest < Test::Unit::TestCase
  1205. def setup
  1206. @klass = Class.new
  1207. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  1208. @second_machine = StateMachine::Machine.new(@klass, :status, :initial => :idling)
  1209. @object = @klass.new
  1210. end
  1211. def test_should_track_each_state_machine
  1212. expected = {:state => @machine, :status => @second_machine}
  1213. assert_equal expected, @klass.state_machines
  1214. end
  1215. def test_should_initialize_state_for_both_machines
  1216. assert_equal 'parked', @object.state
  1217. assert_equal 'idling', @object.status
  1218. end
  1219. end
  1220. class MachineWithExistingMachinesWithSameAttributesOnOwnerClassTest < Test::Unit::TestCase
  1221. def setup
  1222. @klass = Class.new
  1223. @machine = StateMachine::Machine.new(@klass, :initial => :parked)
  1224. @second_machine = StateMachine::Machine.new(@klass, :public_state, :attribute => :state)
  1225. @object = @klass.new
  1226. end
  1227. def test_should_track_each_state_machine
  1228. expected = {:state => @machine, :public_state => @second_machine}
  1229. assert_equal expected, @klass.state_machines
  1230. end
  1231. def test_should_initialize_based_on_first_available_initial_state
  1232. assert_equal 'parked', @object.state
  1233. end
  1234. def test_should_allow_transitions_on_both_machines
  1235. @machine.event :ignite do
  1236. transition :parked => :idling
  1237. end
  1238. @second_machine.event :park do
  1239. transition :idling => :parked
  1240. end
  1241. @object.ignite
  1242. assert_equal 'idling', @object.state
  1243. @object.park
  1244. assert_equal 'parked', @object.state
  1245. end
  1246. end
  1247. class MachineWithNamespaceTest < Test::Unit::TestCase
  1248. def setup
  1249. @klass = Class.new
  1250. @machine = StateMachine::Machine.new(@klass, :namespace => 'alarm', :initial => :active) do
  1251. event :enable do
  1252. transition :off => :active
  1253. end
  1254. event :disable do
  1255. transition :active => :off
  1256. end
  1257. end
  1258. @object = @klass.new
  1259. end
  1260. def test_should_namespace_state_predicates
  1261. [:alarm_active?, :alarm_off?].each do |name|
  1262. assert @object.respond_to?(name)
  1263. end
  1264. end
  1265. def test_should_namespace_event_checks
  1266. [:can_enable_alarm?, :can_disable_alarm?].each do |name|
  1267. assert @object.respond_to?(name)
  1268. end
  1269. end
  1270. def test_should_namespace_event_transition_readers
  1271. [:enable_alarm_transition, :disable_alarm_transition].each do |name|
  1272. assert @object.respond_to?(name)
  1273. end
  1274. end
  1275. def test_should_namespace_events
  1276. [:enable_alarm, :disable_alarm].each do |name|
  1277. assert @object.respond_to?(name)
  1278. end
  1279. end
  1280. def test_should_namespace_bang_events
  1281. [:enable_alarm!, :disable_alarm!].each do |name|
  1282. assert @object.respond_to?(name)
  1283. end
  1284. end
  1285. end
  1286. class MachineWithCustomAttributeTest < Test::Unit::TestCase
  1287. def setup
  1288. StateMachine::Integrations.const_set('Custom', Module.new do
  1289. class << self; attr_reader :defaults; end
  1290. @defaults = {:action => :save, :use_transactions => false}
  1291. def create_with_scope(name)
  1292. lambda {}
  1293. end
  1294. def create_without_scope(name)
  1295. lambda {}
  1296. end
  1297. end)
  1298. @klass = Class.new
  1299. @machine = StateMachine::Machine.new(@klass, :state, :attribute => :state_id, :initial => :active, :integration => :custom) do
  1300. event :ignite do
  1301. transition :parked => :idling
  1302. end
  1303. end
  1304. @object = @klass.new
  1305. end
  1306. def test_should_define_a_reader_attribute_for_the_attribute
  1307. assert @object.respond_to?(:state_id)
  1308. end
  1309. def test_should_define_a_writer_attribute_for_the_attribute
  1310. assert @object.respond_to?(:state_id=)
  1311. end
  1312. def test_should_define_a_predicate_for_the_attribute
  1313. assert @object.respond_to?(:state?)
  1314. end
  1315. def test_should_define_a_name_reader_for_the_attribute
  1316. assert @object.respond_to?(:state_name)
  1317. end
  1318. def test_should_define_an_event_reader_for_the_attribute
  1319. assert @object.respond_to?(:state_events)
  1320. end
  1321. def test_should_define_a_transition_reader_for_the_attribute
  1322. assert @object.respond_to?(:state_transitions)
  1323. end
  1324. def test_should_define_singular_with_scope
  1325. assert @klass.respond_to?(:with_state)
  1326. end
  1327. def test_should_define_singular_without_scope
  1328. assert @klass.respond_to?(:without_state)
  1329. end
  1330. def test_should_define_plural_with_scope
  1331. assert @klass.respond_to?(:with_states)
  1332. end
  1333. def test_should_define_plural_without_scope
  1334. assert @klass.respond_to?(:without_states)
  1335. end
  1336. def test_should_define_state_machines_reader
  1337. expected = {:state => @machine}
  1338. assert_equal expected, @klass.state_machines
  1339. end
  1340. def teardown
  1341. StateMachine::Integrations.send(:remove_const, 'Custom')
  1342. end
  1343. end
  1344. class MachineFinderWithoutExistingMachineTest < Test::Unit::TestCase
  1345. def setup
  1346. @klass = Class.new
  1347. @machine = StateMachine::Machine.find_or_create(@klass)
  1348. end
  1349. def test_should_accept_a_block
  1350. called = false
  1351. StateMachine::Machine.find_or_create(Class.new) do
  1352. called = respond_to?(:event)
  1353. end
  1354. assert called
  1355. end
  1356. def test_should_create_a_new_machine
  1357. assert_not_nil @machine
  1358. end
  1359. def test_should_use_default_state
  1360. assert_equal :state, @machine.attribute
  1361. end
  1362. end
  1363. class MachineFinderWithExistingOnSameClassTest < Test::Unit::TestCase
  1364. def setup
  1365. @klass = Class.new
  1366. @existing_machine = StateMachine::Machine.new(@klass)
  1367. @machine = StateMachine::Machine.find_or_create(@klass)
  1368. end
  1369. def test_should_accept_a_block
  1370. called = false
  1371. StateMachine::Machine.find_or_create(@klass) do
  1372. called = respond_to?(:event)
  1373. end
  1374. assert called
  1375. end
  1376. def test_should_not_create_a_new_machine
  1377. assert_same @machine, @existing_machine
  1378. end
  1379. end
  1380. class MachineFinderWithExistingMachineOnSuperclassTest < Test::Unit::TestCase
  1381. def setup
  1382. integration = Module.new do
  1383. def self.matches?(klass)
  1384. false
  1385. end
  1386. end
  1387. StateMachine::Integrations.const_set('Custom', integration)
  1388. @base_class = Class.new
  1389. @base_machine = StateMachine::Machine.new(@base_class, :status, :action => :save, :integration => :custom)
  1390. @base_machine.event(:ignite) {}
  1391. @base_machine.before_transition(lambda {})
  1392. @base_machine.after_transition(lambda {})
  1393. @klass = Class.new(@base_class)
  1394. @machine = StateMachine::Machine.find_or_create(@klass, :status) {}
  1395. end
  1396. def test_should_accept_a_block
  1397. called = false
  1398. StateMachine::Machine.find_or_create(Class.new(@base_class)) do
  1399. called = respond_to?(:event)
  1400. end
  1401. assert called
  1402. end
  1403. def test_should_not_create_a_new_machine_if_no_block_or_options
  1404. machine = StateMachine::Machine.find_or_create(Class.new(@base_class), :status)
  1405. assert_same machine, @base_machine
  1406. end
  1407. def test_should_create_a_new_machine_if_given_options
  1408. machine = StateMachine::Machine.find_or_create(@klass, :status, :initial => :parked)
  1409. assert_not_nil machine
  1410. assert_not_same machine, @base_machine
  1411. end
  1412. def test_should_create_a_new_machine_if_given_block
  1413. assert_not_nil @machine
  1414. assert_not_same @machine, @base_machine
  1415. end
  1416. def test_should_copy_the_base_attribute
  1417. assert_equal :status, @machine.attribute
  1418. end
  1419. def test_should_copy_the_base_configuration
  1420. assert_equal :save, @machine.action
  1421. end
  1422. def test_should_copy_events
  1423. # Can't assert equal arrays since their machines change
  1424. assert_equal 1, @machine.events.length
  1425. end
  1426. def test_should_copy_before_callbacks
  1427. assert_equal @base_machine.callbacks[:before], @machine.callbacks[:before]
  1428. end
  1429. def test_should_copy_aft

Large files files are truncated, but you can click here to view the full file