PageRenderTime 43ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/test/unit/state_test.rb

http://github.com/pluginaweek/state_machine
Ruby | 1101 lines | 894 code | 206 blank | 1 comment | 3 complexity | f7677ca622161d0cbda974f41572b68d MD5 | raw file
  1. require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
  2. class StateByDefaultTest < Test::Unit::TestCase
  3. def setup
  4. @machine = StateMachine::Machine.new(Class.new)
  5. @machine.states << @state = StateMachine::State.new(@machine, :parked)
  6. end
  7. def test_should_have_a_machine
  8. assert_equal @machine, @state.machine
  9. end
  10. def test_should_have_a_name
  11. assert_equal :parked, @state.name
  12. end
  13. def test_should_have_a_qualified_name
  14. assert_equal :parked, @state.qualified_name
  15. end
  16. def test_should_have_a_human_name
  17. assert_equal 'parked', @state.human_name
  18. end
  19. def test_should_use_stringify_the_name_as_the_value
  20. assert_equal 'parked', @state.value
  21. end
  22. def test_should_not_be_initial
  23. assert !@state.initial
  24. end
  25. def test_should_not_have_a_matcher
  26. assert_nil @state.matcher
  27. end
  28. def test_should_not_have_any_methods
  29. expected = {}
  30. assert_equal expected, @state.context_methods
  31. end
  32. end
  33. class StateTest < Test::Unit::TestCase
  34. def setup
  35. @machine = StateMachine::Machine.new(Class.new)
  36. @machine.states << @state = StateMachine::State.new(@machine, :parked)
  37. end
  38. def test_should_raise_exception_if_invalid_option_specified
  39. exception = assert_raise(ArgumentError) {StateMachine::State.new(@machine, :parked, :invalid => true)}
  40. assert_equal 'Invalid key(s): invalid', exception.message
  41. end
  42. def test_should_allow_changing_machine
  43. new_machine = StateMachine::Machine.new(Class.new)
  44. @state.machine = new_machine
  45. assert_equal new_machine, @state.machine
  46. end
  47. def test_should_allow_changing_value
  48. @state.value = 1
  49. assert_equal 1, @state.value
  50. end
  51. def test_should_allow_changing_initial
  52. @state.initial = true
  53. assert @state.initial
  54. end
  55. def test_should_allow_changing_matcher
  56. matcher = lambda {}
  57. @state.matcher = matcher
  58. assert_equal matcher, @state.matcher
  59. end
  60. def test_should_allow_changing_human_name
  61. @state.human_name = 'stopped'
  62. assert_equal 'stopped', @state.human_name
  63. end
  64. def test_should_use_pretty_inspect
  65. assert_equal '#<StateMachine::State name=:parked value="parked" initial=false>', @state.inspect
  66. end
  67. end
  68. class StateWithoutNameTest < Test::Unit::TestCase
  69. def setup
  70. @klass = Class.new
  71. @machine = StateMachine::Machine.new(@klass)
  72. @machine.states << @state = StateMachine::State.new(@machine, nil)
  73. end
  74. def test_should_have_a_nil_name
  75. assert_nil @state.name
  76. end
  77. def test_should_have_a_nil_qualified_name
  78. assert_nil @state.qualified_name
  79. end
  80. def test_should_have_an_empty_human_name
  81. assert_equal 'nil', @state.human_name
  82. end
  83. def test_should_have_a_nil_value
  84. assert_nil @state.value
  85. end
  86. def test_should_not_redefine_nil_predicate
  87. object = @klass.new
  88. assert !object.nil?
  89. assert !object.respond_to?('?')
  90. end
  91. def test_should_have_a_description
  92. assert_equal 'nil', @state.description
  93. end
  94. def test_should_have_a_description_using_human_name
  95. assert_equal 'nil', @state.description(:human_name => true)
  96. end
  97. end
  98. class StateWithNameTest < Test::Unit::TestCase
  99. def setup
  100. @klass = Class.new
  101. @machine = StateMachine::Machine.new(@klass)
  102. @machine.states << @state = StateMachine::State.new(@machine, :parked)
  103. end
  104. def test_should_have_a_name
  105. assert_equal :parked, @state.name
  106. end
  107. def test_should_have_a_qualified_name
  108. assert_equal :parked, @state.name
  109. end
  110. def test_should_have_a_human_name
  111. assert_equal 'parked', @state.human_name
  112. end
  113. def test_should_use_stringify_the_name_as_the_value
  114. assert_equal 'parked', @state.value
  115. end
  116. def test_should_match_stringified_name
  117. assert @state.matches?('parked')
  118. assert !@state.matches?('idling')
  119. end
  120. def test_should_not_include_value_in_description
  121. assert_equal 'parked', @state.description
  122. end
  123. def test_should_allow_using_human_name_in_description
  124. @state.human_name = 'Parked'
  125. assert_equal 'Parked', @state.description(:human_name => true)
  126. end
  127. def test_should_define_predicate
  128. assert @klass.new.respond_to?(:parked?)
  129. end
  130. end
  131. class StateWithNilValueTest < Test::Unit::TestCase
  132. def setup
  133. @klass = Class.new
  134. @machine = StateMachine::Machine.new(@klass)
  135. @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => nil)
  136. end
  137. def test_should_have_a_name
  138. assert_equal :parked, @state.name
  139. end
  140. def test_should_have_a_nil_value
  141. assert_nil @state.value
  142. end
  143. def test_should_match_nil_values
  144. assert @state.matches?(nil)
  145. end
  146. def test_should_have_a_description
  147. assert_equal 'parked (nil)', @state.description
  148. end
  149. def test_should_have_a_description_with_human_name
  150. @state.human_name = 'Parked'
  151. assert_equal 'Parked (nil)', @state.description(:human_name => true)
  152. end
  153. def test_should_define_predicate
  154. object = @klass.new
  155. assert object.respond_to?(:parked?)
  156. end
  157. end
  158. class StateWithSymbolicValueTest < Test::Unit::TestCase
  159. def setup
  160. @klass = Class.new
  161. @machine = StateMachine::Machine.new(@klass)
  162. @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => :parked)
  163. end
  164. def test_should_use_custom_value
  165. assert_equal :parked, @state.value
  166. end
  167. def test_should_not_include_value_in_description
  168. assert_equal 'parked', @state.description
  169. end
  170. def test_should_allow_human_name_in_description
  171. @state.human_name = 'Parked'
  172. assert_equal 'Parked', @state.description(:human_name => true)
  173. end
  174. def test_should_match_symbolic_value
  175. assert @state.matches?(:parked)
  176. assert !@state.matches?('parked')
  177. end
  178. def test_should_define_predicate
  179. object = @klass.new
  180. assert object.respond_to?(:parked?)
  181. end
  182. end
  183. class StateWithIntegerValueTest < Test::Unit::TestCase
  184. def setup
  185. @klass = Class.new
  186. @machine = StateMachine::Machine.new(@klass)
  187. @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => 1)
  188. end
  189. def test_should_use_custom_value
  190. assert_equal 1, @state.value
  191. end
  192. def test_should_include_value_in_description
  193. assert_equal 'parked (1)', @state.description
  194. end
  195. def test_should_allow_human_name_in_description
  196. @state.human_name = 'Parked'
  197. assert_equal 'Parked (1)', @state.description(:human_name => true)
  198. end
  199. def test_should_match_integer_value
  200. assert @state.matches?(1)
  201. assert !@state.matches?(2)
  202. end
  203. def test_should_define_predicate
  204. object = @klass.new
  205. assert object.respond_to?(:parked?)
  206. end
  207. end
  208. class StateWithLambdaValueTest < Test::Unit::TestCase
  209. def setup
  210. @klass = Class.new
  211. @args = nil
  212. @machine = StateMachine::Machine.new(@klass)
  213. @value = lambda {|*args| @args = args; :parked}
  214. @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => @value)
  215. end
  216. def test_should_use_evaluated_value_by_default
  217. assert_equal :parked, @state.value
  218. end
  219. def test_should_allow_access_to_original_value
  220. assert_equal @value, @state.value(false)
  221. end
  222. def test_should_include_masked_value_in_description
  223. assert_equal 'parked (*)', @state.description
  224. end
  225. def test_should_not_pass_in_any_arguments
  226. @state.value
  227. assert_equal [], @args
  228. end
  229. def test_should_define_predicate
  230. object = @klass.new
  231. assert object.respond_to?(:parked?)
  232. end
  233. def test_should_match_evaluated_value
  234. assert @state.matches?(:parked)
  235. end
  236. end
  237. class StateWithCachedLambdaValueTest < Test::Unit::TestCase
  238. def setup
  239. @klass = Class.new
  240. @machine = StateMachine::Machine.new(@klass)
  241. @dynamic_value = lambda {'value'}
  242. @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => @dynamic_value, :cache => true)
  243. end
  244. def test_should_be_caching
  245. assert @state.cache
  246. end
  247. def test_should_evaluate_value
  248. assert_equal 'value', @state.value
  249. end
  250. def test_should_only_evaluate_value_once
  251. value = @state.value
  252. assert_same value, @state.value
  253. end
  254. def test_should_update_value_index_for_state_collection
  255. @state.value
  256. assert_equal @state, @machine.states['value', :value]
  257. assert_nil @machine.states[@dynamic_value, :value]
  258. end
  259. end
  260. class StateWithoutCachedLambdaValueTest < Test::Unit::TestCase
  261. def setup
  262. @klass = Class.new
  263. @machine = StateMachine::Machine.new(@klass)
  264. @dynamic_value = lambda {'value'}
  265. @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => @dynamic_value)
  266. end
  267. def test_should_not_be_caching
  268. assert !@state.cache
  269. end
  270. def test_should_evaluate_value_each_time
  271. value = @state.value
  272. assert_not_same value, @state.value
  273. end
  274. def test_should_not_update_value_index_for_state_collection
  275. @state.value
  276. assert_nil @machine.states['value', :value]
  277. assert_equal @state, @machine.states[@dynamic_value, :value]
  278. end
  279. end
  280. class StateWithMatcherTest < Test::Unit::TestCase
  281. def setup
  282. @klass = Class.new
  283. @args = nil
  284. @machine = StateMachine::Machine.new(@klass)
  285. @machine.states << @state = StateMachine::State.new(@machine, :parked, :if => lambda {|value| value == 1})
  286. end
  287. def test_should_not_match_actual_value
  288. assert !@state.matches?('parked')
  289. end
  290. def test_should_match_evaluated_block
  291. assert @state.matches?(1)
  292. end
  293. end
  294. class StateWithHumanNameTest < Test::Unit::TestCase
  295. def setup
  296. @klass = Class.new
  297. @machine = StateMachine::Machine.new(@klass)
  298. @machine.states << @state = StateMachine::State.new(@machine, :parked, :human_name => 'stopped')
  299. end
  300. def test_should_use_custom_human_name
  301. assert_equal 'stopped', @state.human_name
  302. end
  303. end
  304. class StateWithDynamicHumanNameTest < Test::Unit::TestCase
  305. def setup
  306. @klass = Class.new
  307. @machine = StateMachine::Machine.new(@klass)
  308. @machine.states << @state = StateMachine::State.new(@machine, :parked, :human_name => lambda {|state, object| ['stopped', object]})
  309. end
  310. def test_should_use_custom_human_name
  311. human_name, klass = @state.human_name
  312. assert_equal 'stopped', human_name
  313. assert_equal @klass, klass
  314. end
  315. def test_should_allow_custom_class_to_be_passed_through
  316. human_name, klass = @state.human_name(1)
  317. assert_equal 'stopped', human_name
  318. assert_equal 1, klass
  319. end
  320. def test_should_not_cache_value
  321. assert_not_same @state.human_name, @state.human_name
  322. end
  323. end
  324. class StateInitialTest < Test::Unit::TestCase
  325. def setup
  326. @machine = StateMachine::Machine.new(Class.new)
  327. @machine.states << @state = StateMachine::State.new(@machine, :parked, :initial => true)
  328. end
  329. def test_should_be_initial
  330. assert @state.initial
  331. assert @state.initial?
  332. end
  333. end
  334. class StateNotInitialTest < Test::Unit::TestCase
  335. def setup
  336. @machine = StateMachine::Machine.new(Class.new)
  337. @machine.states << @state = StateMachine::State.new(@machine, :parked, :initial => false)
  338. end
  339. def test_should_not_be_initial
  340. assert !@state.initial
  341. assert !@state.initial?
  342. end
  343. end
  344. class StateFinalTest < Test::Unit::TestCase
  345. def setup
  346. @machine = StateMachine::Machine.new(Class.new)
  347. @machine.states << @state = StateMachine::State.new(@machine, :parked)
  348. end
  349. def test_should_be_final_without_input_transitions
  350. assert @state.final?
  351. end
  352. def test_should_be_final_with_input_transitions
  353. @machine.event :park do
  354. transition :idling => :parked
  355. end
  356. assert @state.final?
  357. end
  358. def test_should_be_final_with_loopback
  359. @machine.event :ignite do
  360. transition :parked => same
  361. end
  362. assert @state.final?
  363. end
  364. end
  365. class StateNotFinalTest < Test::Unit::TestCase
  366. def setup
  367. @machine = StateMachine::Machine.new(Class.new)
  368. @machine.states << @state = StateMachine::State.new(@machine, :parked)
  369. end
  370. def test_should_not_be_final_with_outgoing_whitelist_transitions
  371. @machine.event :ignite do
  372. transition :parked => :idling
  373. end
  374. assert !@state.final?
  375. end
  376. def test_should_not_be_final_with_outgoing_all_transitions
  377. @machine.event :ignite do
  378. transition all => :idling
  379. end
  380. assert !@state.final?
  381. end
  382. def test_should_not_be_final_with_outgoing_blacklist_transitions
  383. @machine.event :ignite do
  384. transition all - :first_gear => :idling
  385. end
  386. assert !@state.final?
  387. end
  388. end
  389. class StateWithConflictingHelpersBeforeDefinitionTest < Test::Unit::TestCase
  390. def setup
  391. require 'stringio'
  392. @original_stderr, $stderr = $stderr, StringIO.new
  393. @superclass = Class.new do
  394. def parked?
  395. 0
  396. end
  397. end
  398. @klass = Class.new(@superclass)
  399. @machine = StateMachine::Machine.new(@klass)
  400. @machine.state :parked
  401. @object = @klass.new
  402. end
  403. def test_should_not_override_state_predicate
  404. assert_equal 0, @object.parked?
  405. end
  406. def test_should_output_warning
  407. assert_equal "Instance method \"parked?\" is already defined in #{@superclass.to_s}, use generic helper instead or set StateMachine::Machine.ignore_method_conflicts = true.\n", $stderr.string
  408. end
  409. def teardown
  410. $stderr = @original_stderr
  411. end
  412. end
  413. class StateWithConflictingHelpersAfterDefinitionTest < Test::Unit::TestCase
  414. def setup
  415. require 'stringio'
  416. @original_stderr, $stderr = $stderr, StringIO.new
  417. @klass = Class.new do
  418. def parked?
  419. 0
  420. end
  421. end
  422. @machine = StateMachine::Machine.new(@klass)
  423. @machine.state :parked
  424. @object = @klass.new
  425. end
  426. def test_should_not_override_state_predicate
  427. assert_equal 0, @object.parked?
  428. end
  429. def test_should_still_allow_super_chaining
  430. @klass.class_eval do
  431. def parked?
  432. super
  433. end
  434. end
  435. assert_equal false, @object.parked?
  436. end
  437. def test_should_not_output_warning
  438. assert_equal '', $stderr.string
  439. end
  440. def teardown
  441. $stderr = @original_stderr
  442. end
  443. end
  444. class StateWithConflictingMachineTest < Test::Unit::TestCase
  445. def setup
  446. require 'stringio'
  447. @original_stderr, $stderr = $stderr, StringIO.new
  448. @klass = Class.new
  449. @state_machine = StateMachine::Machine.new(@klass, :state)
  450. @state_machine.states << @state = StateMachine::State.new(@state_machine, :parked)
  451. end
  452. def test_should_output_warning_if_using_different_attribute
  453. @status_machine = StateMachine::Machine.new(@klass, :status)
  454. @status_machine.states << @state = StateMachine::State.new(@status_machine, :parked)
  455. assert_equal "State :parked for :status is already defined in :state\n", $stderr.string
  456. end
  457. def test_should_not_output_warning_if_using_same_attribute
  458. @status_machine = StateMachine::Machine.new(@klass, :status, :attribute => :state)
  459. @status_machine.states << @state = StateMachine::State.new(@status_machine, :parked)
  460. assert_equal '', $stderr.string
  461. end
  462. def test_should_not_output_warning_if_using_different_namespace
  463. @status_machine = StateMachine::Machine.new(@klass, :status, :namespace => 'alarm')
  464. @status_machine.states << @state = StateMachine::State.new(@status_machine, :parked)
  465. assert_equal '', $stderr.string
  466. end
  467. def teardown
  468. $stderr = @original_stderr
  469. end
  470. end
  471. class StateWithConflictingMachineNameTest < Test::Unit::TestCase
  472. def setup
  473. require 'stringio'
  474. @original_stderr, $stderr = $stderr, StringIO.new
  475. @klass = Class.new
  476. @state_machine = StateMachine::Machine.new(@klass, :state)
  477. end
  478. def test_should_output_warning_if_name_conflicts
  479. StateMachine::State.new(@state_machine, :state)
  480. assert_equal "Instance method \"state?\" is already defined in #{@klass} :state instance helpers, use generic helper instead or set StateMachine::Machine.ignore_method_conflicts = true.\n", $stderr.string
  481. end
  482. def teardown
  483. $stderr = @original_stderr
  484. end
  485. end
  486. class StateWithNamespaceTest < Test::Unit::TestCase
  487. def setup
  488. @klass = Class.new
  489. @machine = StateMachine::Machine.new(@klass, :namespace => 'alarm')
  490. @machine.states << @state = StateMachine::State.new(@machine, :active)
  491. @object = @klass.new
  492. end
  493. def test_should_have_a_name
  494. assert_equal :active, @state.name
  495. end
  496. def test_should_have_a_qualified_name
  497. assert_equal :alarm_active, @state.qualified_name
  498. end
  499. def test_should_namespace_predicate
  500. assert @object.respond_to?(:alarm_active?)
  501. end
  502. end
  503. class StateAfterBeingCopiedTest < Test::Unit::TestCase
  504. def setup
  505. @machine = StateMachine::Machine.new(Class.new)
  506. @machine.states << @state = StateMachine::State.new(@machine, :parked)
  507. @copied_state = @state.dup
  508. end
  509. def test_should_not_have_the_context
  510. state_context = nil
  511. @state.context { state_context = self }
  512. copied_state_context = nil
  513. @copied_state.context { copied_state_context = self }
  514. assert_not_same state_context, copied_state_context
  515. end
  516. end
  517. class StateWithContextTest < Test::Unit::TestCase
  518. def setup
  519. @klass = Class.new
  520. @machine = StateMachine::Machine.new(@klass)
  521. @ancestors = @klass.ancestors
  522. @machine.states << @state = StateMachine::State.new(@machine, :idling)
  523. context = nil
  524. speed_method = nil
  525. rpm_method = nil
  526. @result = @state.context do
  527. context = self
  528. def speed
  529. 0
  530. end
  531. speed_method = instance_method(:speed)
  532. def rpm
  533. 1000
  534. end
  535. rpm_method = instance_method(:rpm)
  536. end
  537. @context = context
  538. @speed_method = speed_method
  539. @rpm_method = rpm_method
  540. end
  541. def test_should_return_true
  542. assert_equal true, @result
  543. end
  544. def test_should_include_new_module_in_owner_class
  545. assert_not_equal @ancestors, @klass.ancestors
  546. assert_equal [@context], @klass.ancestors - @ancestors
  547. end
  548. def test_should_define_each_context_method_in_owner_class
  549. %w(speed rpm).each {|method| assert @klass.method_defined?(method)}
  550. end
  551. def test_should_define_aliased_context_method_in_owner_class
  552. %w(speed rpm).each {|method| assert @klass.method_defined?("__state_idling_#{method}_#{@context.object_id}__")}
  553. end
  554. def test_should_not_use_context_methods_as_owner_class_methods
  555. assert_not_equal @speed_method, @state.context_methods[:speed]
  556. assert_not_equal @rpm_method, @state.context_methods[:rpm]
  557. end
  558. def test_should_use_context_methods_as_aliased_owner_class_methods
  559. assert_equal @speed_method, @state.context_methods[:"__state_idling_speed_#{@context.object_id}__"]
  560. assert_equal @rpm_method, @state.context_methods[:"__state_idling_rpm_#{@context.object_id}__"]
  561. end
  562. end
  563. class StateWithMultipleContextsTest < Test::Unit::TestCase
  564. def setup
  565. @klass = Class.new
  566. @machine = StateMachine::Machine.new(@klass)
  567. @ancestors = @klass.ancestors
  568. @machine.states << @state = StateMachine::State.new(@machine, :idling)
  569. context = nil
  570. speed_method = nil
  571. @state.context do
  572. context = self
  573. def speed
  574. 0
  575. end
  576. speed_method = instance_method(:speed)
  577. end
  578. @context = context
  579. @speed_method = speed_method
  580. rpm_method = nil
  581. @state.context do
  582. def rpm
  583. 1000
  584. end
  585. rpm_method = instance_method(:rpm)
  586. end
  587. @rpm_method = rpm_method
  588. end
  589. def test_should_include_new_module_in_owner_class
  590. assert_not_equal @ancestors, @klass.ancestors
  591. assert_equal [@context], @klass.ancestors - @ancestors
  592. end
  593. def test_should_define_each_context_method_in_owner_class
  594. %w(speed rpm).each {|method| assert @klass.method_defined?(method)}
  595. end
  596. def test_should_define_aliased_context_method_in_owner_class
  597. %w(speed rpm).each {|method| assert @klass.method_defined?("__state_idling_#{method}_#{@context.object_id}__")}
  598. end
  599. def test_should_not_use_context_methods_as_owner_class_methods
  600. assert_not_equal @speed_method, @state.context_methods[:speed]
  601. assert_not_equal @rpm_method, @state.context_methods[:rpm]
  602. end
  603. def test_should_use_context_methods_as_aliased_owner_class_methods
  604. assert_equal @speed_method, @state.context_methods[:"__state_idling_speed_#{@context.object_id}__"]
  605. assert_equal @rpm_method, @state.context_methods[:"__state_idling_rpm_#{@context.object_id}__"]
  606. end
  607. end
  608. class StateWithExistingContextMethodTest < Test::Unit::TestCase
  609. def setup
  610. @klass = Class.new do
  611. def speed
  612. 60
  613. end
  614. end
  615. @original_speed_method = @klass.instance_method(:speed)
  616. @machine = StateMachine::Machine.new(@klass)
  617. @machine.states << @state = StateMachine::State.new(@machine, :idling)
  618. @state.context do
  619. def speed
  620. 0
  621. end
  622. end
  623. end
  624. def test_should_not_override_method
  625. assert_equal @original_speed_method, @klass.instance_method(:speed)
  626. end
  627. end
  628. class StateWithRedefinedContextMethodTest < Test::Unit::TestCase
  629. def setup
  630. @klass = Class.new
  631. @machine = StateMachine::Machine.new(@klass)
  632. @machine.states << @state = StateMachine::State.new(@machine, 'on')
  633. old_context = nil
  634. old_speed_method = nil
  635. @state.context do
  636. old_context = self
  637. def speed
  638. 0
  639. end
  640. old_speed_method = instance_method(:speed)
  641. end
  642. @old_context = old_context
  643. @old_speed_method = old_speed_method
  644. current_context = nil
  645. current_speed_method = nil
  646. @state.context do
  647. current_context = self
  648. def speed
  649. 'green'
  650. end
  651. current_speed_method = instance_method(:speed)
  652. end
  653. @current_context = current_context
  654. @current_speed_method = current_speed_method
  655. end
  656. def test_should_track_latest_defined_method
  657. assert_equal @current_speed_method, @state.context_methods[:"__state_on_speed_#{@current_context.object_id}__"]
  658. end
  659. def test_should_have_the_same_context
  660. assert_equal @current_context, @old_context
  661. end
  662. end
  663. class StateWithInvalidMethodCallTest < Test::Unit::TestCase
  664. def setup
  665. @klass = Class.new
  666. @machine = StateMachine::Machine.new(@klass)
  667. @ancestors = @klass.ancestors
  668. @machine.states << @state = StateMachine::State.new(@machine, :idling)
  669. @state.context do
  670. def speed
  671. 0
  672. end
  673. end
  674. @object = @klass.new
  675. end
  676. def test_should_call_method_missing_arg
  677. assert_equal 1, @state.call(@object, :invalid, :method_missing => lambda {1})
  678. end
  679. end
  680. class StateWithValidMethodCallForDifferentStateTest < Test::Unit::TestCase
  681. def setup
  682. @klass = Class.new
  683. @machine = StateMachine::Machine.new(@klass)
  684. @ancestors = @klass.ancestors
  685. @machine.states << @state = StateMachine::State.new(@machine, :idling)
  686. @state.context do
  687. def speed
  688. 0
  689. end
  690. end
  691. @object = @klass.new
  692. end
  693. def test_should_call_method_missing_arg
  694. assert_equal 1, @state.call(@object, :speed, :method_missing => lambda {1})
  695. end
  696. def test_should_raise_invalid_context_on_no_method_error
  697. exception = assert_raise(StateMachine::InvalidContext) do
  698. @state.call(@object, :speed, :method_missing => lambda { raise NoMethodError.new('Invalid', :speed, [])})
  699. end
  700. assert_equal @object, exception.object
  701. assert_equal 'State nil for :state is not a valid context for calling #speed', exception.message
  702. end
  703. def test_should_raise_original_error_on_no_method_error_with_different_arguments
  704. assert_raise(NoMethodError) do
  705. @state.call(@object, :speed, :method_missing => lambda { raise NoMethodError.new('Invalid', :speed, [1])})
  706. end
  707. end
  708. def test_should_raise_original_error_on_no_method_error_for_different_method
  709. assert_raise(NoMethodError) do
  710. @state.call(@object, :speed, :method_missing => lambda { raise NoMethodError.new('Invalid', :rpm, [])})
  711. end
  712. end
  713. end
  714. class StateWithValidMethodCallForCurrentStateTest < Test::Unit::TestCase
  715. def setup
  716. @klass = Class.new
  717. @machine = StateMachine::Machine.new(@klass, :initial => :idling)
  718. @ancestors = @klass.ancestors
  719. @state = @machine.state(:idling)
  720. @state.context do
  721. def speed(arg = nil)
  722. block_given? ? [arg, yield] : arg
  723. end
  724. end
  725. @object = @klass.new
  726. end
  727. def test_should_not_raise_an_exception
  728. assert_nothing_raised { @state.call(@object, :speed, :method_missing => lambda {raise}) }
  729. end
  730. def test_should_pass_arguments_through
  731. assert_equal 1, @state.call(@object, :speed, 1, :method_missing => lambda {})
  732. end
  733. def test_should_pass_blocks_through
  734. assert_equal [nil, 1], @state.call(@object, :speed) {1}
  735. end
  736. def test_should_pass_both_arguments_and_blocks_through
  737. assert_equal [1, 2], @state.call(@object, :speed, 1, :method_missing => lambda {}) {2}
  738. end
  739. end
  740. if RUBY_VERSION > '1.8.7'
  741. class StateWithValidInheritedMethodCallForCurrentStateTest < Test::Unit::TestCase
  742. def setup
  743. @superclass = Class.new do
  744. def speed(arg = nil)
  745. [arg]
  746. end
  747. end
  748. @klass = Class.new(@superclass)
  749. @machine = StateMachine::Machine.new(@klass, :initial => :idling)
  750. @ancestors = @klass.ancestors
  751. @state = @machine.state(:idling)
  752. @state.context do
  753. def speed(arg = nil)
  754. [arg] + super(2)
  755. end
  756. end
  757. @object = @klass.new
  758. end
  759. def test_should_not_raise_an_exception
  760. assert_nothing_raised { @state.call(@object, :speed, :method_missing => lambda {raise}) }
  761. end
  762. def test_should_be_able_to_call_super
  763. assert_equal [1, 2], @state.call(@object, :speed, 1)
  764. end
  765. def test_should_allow_redefinition
  766. @state.context do
  767. def speed(arg = nil)
  768. [arg] + super(3)
  769. end
  770. end
  771. assert_equal [1, 3], @state.call(@object, :speed, 1)
  772. end
  773. end
  774. end
  775. begin
  776. # Load library
  777. require 'graphviz'
  778. class StateDrawingTest < Test::Unit::TestCase
  779. def setup
  780. @machine = StateMachine::Machine.new(Class.new)
  781. @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => 1)
  782. @machine.event :ignite do
  783. transition :parked => :idling
  784. end
  785. graph = StateMachine::Graph.new('test')
  786. @state.draw(graph)
  787. @node = graph.get_node('parked')
  788. end
  789. def test_should_use_ellipse_shape
  790. assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
  791. end
  792. def test_should_set_width_to_one
  793. assert_equal '1', @node['width'].to_s.gsub('"', '')
  794. end
  795. def test_should_set_height_to_one
  796. assert_equal '1', @node['height'].to_s.gsub('"', '')
  797. end
  798. def test_should_use_description_as_label
  799. assert_equal 'parked (1)', @node['label'].to_s.gsub('"', '')
  800. end
  801. end
  802. class StateDrawingInitialTest < Test::Unit::TestCase
  803. def setup
  804. @machine = StateMachine::Machine.new(Class.new)
  805. @machine.states << @state = StateMachine::State.new(@machine, :parked, :initial => true)
  806. @machine.event :ignite do
  807. transition :parked => :idling
  808. end
  809. @graph = StateMachine::Graph.new('test')
  810. @state.draw(@graph)
  811. @node = @graph.get_node('parked')
  812. end
  813. def test_should_use_ellipse_as_shape
  814. assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
  815. end
  816. def test_should_draw_edge_between_point_and_state
  817. assert_equal 2, @graph.node_count
  818. assert_equal 1, @graph.edge_count
  819. end
  820. end
  821. class StateDrawingNilNameTest < Test::Unit::TestCase
  822. def setup
  823. @machine = StateMachine::Machine.new(Class.new)
  824. @machine.states << @state = StateMachine::State.new(@machine, nil)
  825. graph = StateMachine::Graph.new('test')
  826. @state.draw(graph)
  827. @node = graph.get_node('nil')
  828. end
  829. def test_should_have_a_node
  830. assert_not_nil @node
  831. end
  832. def test_should_use_description_as_label
  833. assert_equal 'nil', @node['label'].to_s.gsub('"', '')
  834. end
  835. end
  836. class StateDrawingLambdaValueTest < Test::Unit::TestCase
  837. def setup
  838. @machine = StateMachine::Machine.new(Class.new)
  839. @machine.states << @state = StateMachine::State.new(@machine, :parked, :value => lambda {})
  840. graph = StateMachine::Graph.new('test')
  841. @state.draw(graph)
  842. @node = graph.get_node('parked')
  843. end
  844. def test_should_have_a_node
  845. assert_not_nil @node
  846. end
  847. def test_should_use_description_as_label
  848. assert_equal 'parked (*)', @node['label'].to_s.gsub('"', '')
  849. end
  850. end
  851. class StateDrawingNonFinalTest < Test::Unit::TestCase
  852. def setup
  853. @machine = StateMachine::Machine.new(Class.new)
  854. @machine.states << @state = StateMachine::State.new(@machine, :parked)
  855. @machine.event :ignite do
  856. transition :parked => :idling
  857. end
  858. graph = StateMachine::Graph.new('test')
  859. @state.draw(graph)
  860. @node = graph.get_node('parked')
  861. end
  862. def test_should_use_ellipse_as_shape
  863. assert_equal 'ellipse', @node['shape'].to_s.gsub('"', '')
  864. end
  865. end
  866. class StateDrawingFinalTest < Test::Unit::TestCase
  867. def setup
  868. @machine = StateMachine::Machine.new(Class.new)
  869. @machine.states << @state = StateMachine::State.new(@machine, :parked)
  870. graph = StateMachine::Graph.new('test')
  871. @state.draw(graph)
  872. @node = graph.get_node('parked')
  873. end
  874. def test_should_use_doublecircle_as_shape
  875. assert_equal 'doublecircle', @node['shape'].to_s.gsub('"', '')
  876. end
  877. end
  878. class StateDrawingWithHumanNameTest < Test::Unit::TestCase
  879. def setup
  880. @machine = StateMachine::Machine.new(Class.new)
  881. @machine.states << @state = StateMachine::State.new(@machine, :parked, :human_name => 'Parked')
  882. @machine.event :ignite do
  883. transition :parked => :idling
  884. end
  885. graph = StateMachine::Graph.new('test')
  886. @state.draw(graph, :human_name => true)
  887. @node = graph.get_node('parked')
  888. end
  889. def test_should_use_description_with_human_name_as_label
  890. assert_equal 'Parked', @node['label'].to_s.gsub('"', '')
  891. end
  892. end
  893. rescue LoadError
  894. $stderr.puts 'Skipping GraphViz StateMachine::State tests. `gem install ruby-graphviz` >= v0.9.17 and try again.'
  895. end unless ENV['TRAVIS']