PageRenderTime 52ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/test/unit/machine_test.rb

https://github.com/johnsonzes/state_machine
Ruby | 2674 lines | 2127 code | 545 blank | 2 comment | 19 complexity | 7923ac9e565ba02ce65c742d4bd644ba MD5 | raw file

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

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