state_machine 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. data/.gitignore +11 -0
  2. data/.travis.yml +16 -0
  3. data/.yardopts +5 -0
  4. data/Appraisals +260 -0
  5. data/CHANGELOG.rdoc +15 -0
  6. data/Gemfile +3 -0
  7. data/README.rdoc +156 -29
  8. data/Rakefile +31 -57
  9. data/gemfiles/active_model-3.0.0.gemfile +7 -0
  10. data/gemfiles/active_model-3.0.0.gemfile.lock +32 -0
  11. data/gemfiles/active_model-3.0.5.gemfile +7 -0
  12. data/gemfiles/active_model-3.0.5.gemfile.lock +32 -0
  13. data/gemfiles/active_record-2.0.0.gemfile +8 -0
  14. data/gemfiles/active_record-2.0.0.gemfile.lock +30 -0
  15. data/gemfiles/active_record-2.0.5.gemfile +8 -0
  16. data/gemfiles/active_record-2.0.5.gemfile.lock +30 -0
  17. data/gemfiles/active_record-2.1.0.gemfile +8 -0
  18. data/gemfiles/active_record-2.1.0.gemfile.lock +30 -0
  19. data/gemfiles/active_record-2.1.2.gemfile +8 -0
  20. data/gemfiles/active_record-2.1.2.gemfile.lock +30 -0
  21. data/gemfiles/active_record-2.2.3.gemfile +8 -0
  22. data/gemfiles/active_record-2.2.3.gemfile.lock +30 -0
  23. data/gemfiles/active_record-2.3.12.gemfile +8 -0
  24. data/gemfiles/active_record-2.3.12.gemfile.lock +30 -0
  25. data/gemfiles/active_record-3.0.0.gemfile +8 -0
  26. data/gemfiles/active_record-3.0.0.gemfile.lock +44 -0
  27. data/gemfiles/active_record-3.0.5.gemfile +8 -0
  28. data/gemfiles/active_record-3.0.5.gemfile.lock +43 -0
  29. data/gemfiles/data_mapper-0.10.2.gemfile +12 -0
  30. data/gemfiles/data_mapper-0.10.2.gemfile.lock +45 -0
  31. data/gemfiles/data_mapper-0.9.11.gemfile +12 -0
  32. data/gemfiles/data_mapper-0.9.11.gemfile.lock +47 -0
  33. data/gemfiles/data_mapper-0.9.4.gemfile +12 -0
  34. data/gemfiles/data_mapper-0.9.4.gemfile.lock +61 -0
  35. data/gemfiles/data_mapper-0.9.7.gemfile +12 -0
  36. data/gemfiles/data_mapper-0.9.7.gemfile.lock +57 -0
  37. data/gemfiles/data_mapper-1.0.0.gemfile +12 -0
  38. data/gemfiles/data_mapper-1.0.0.gemfile.lock +53 -0
  39. data/gemfiles/data_mapper-1.0.1.gemfile +12 -0
  40. data/gemfiles/data_mapper-1.0.1.gemfile.lock +53 -0
  41. data/gemfiles/data_mapper-1.0.2.gemfile +12 -0
  42. data/gemfiles/data_mapper-1.0.2.gemfile.lock +53 -0
  43. data/gemfiles/data_mapper-1.1.0.gemfile +12 -0
  44. data/gemfiles/data_mapper-1.1.0.gemfile.lock +51 -0
  45. data/gemfiles/default.gemfile +7 -0
  46. data/gemfiles/default.gemfile.lock +24 -0
  47. data/gemfiles/mongo_mapper-0.5.5.gemfile +8 -0
  48. data/gemfiles/mongo_mapper-0.5.5.gemfile.lock +33 -0
  49. data/gemfiles/mongo_mapper-0.5.8.gemfile +8 -0
  50. data/gemfiles/mongo_mapper-0.5.8.gemfile.lock +33 -0
  51. data/gemfiles/mongo_mapper-0.6.0.gemfile +8 -0
  52. data/gemfiles/mongo_mapper-0.6.0.gemfile.lock +33 -0
  53. data/gemfiles/mongo_mapper-0.6.10.gemfile +8 -0
  54. data/gemfiles/mongo_mapper-0.6.10.gemfile.lock +33 -0
  55. data/gemfiles/mongo_mapper-0.7.0.gemfile +8 -0
  56. data/gemfiles/mongo_mapper-0.7.0.gemfile.lock +33 -0
  57. data/gemfiles/mongo_mapper-0.7.5.gemfile +8 -0
  58. data/gemfiles/mongo_mapper-0.7.5.gemfile.lock +36 -0
  59. data/gemfiles/mongo_mapper-0.8.0.gemfile +10 -0
  60. data/gemfiles/mongo_mapper-0.8.0.gemfile.lock +40 -0
  61. data/gemfiles/mongo_mapper-0.8.3.gemfile +10 -0
  62. data/gemfiles/mongo_mapper-0.8.3.gemfile.lock +40 -0
  63. data/gemfiles/mongo_mapper-0.8.4.gemfile +8 -0
  64. data/gemfiles/mongo_mapper-0.8.4.gemfile.lock +38 -0
  65. data/gemfiles/mongo_mapper-0.8.6.gemfile +8 -0
  66. data/gemfiles/mongo_mapper-0.8.6.gemfile.lock +38 -0
  67. data/gemfiles/mongo_mapper-0.9.0.gemfile +7 -0
  68. data/gemfiles/mongo_mapper-0.9.0.gemfile.lock +41 -0
  69. data/gemfiles/mongoid-2.0.0.gemfile +7 -0
  70. data/gemfiles/mongoid-2.0.0.gemfile.lock +42 -0
  71. data/gemfiles/mongoid-2.1.4.gemfile +7 -0
  72. data/gemfiles/mongoid-2.1.4.gemfile.lock +40 -0
  73. data/gemfiles/sequel-2.11.0.gemfile +8 -0
  74. data/gemfiles/sequel-2.11.0.gemfile.lock +28 -0
  75. data/gemfiles/sequel-2.12.0.gemfile +8 -0
  76. data/gemfiles/sequel-2.12.0.gemfile.lock +28 -0
  77. data/gemfiles/sequel-2.8.0.gemfile +8 -0
  78. data/gemfiles/sequel-2.8.0.gemfile.lock +28 -0
  79. data/gemfiles/sequel-3.0.0.gemfile +8 -0
  80. data/gemfiles/sequel-3.0.0.gemfile.lock +28 -0
  81. data/gemfiles/sequel-3.13.0.gemfile +8 -0
  82. data/gemfiles/sequel-3.13.0.gemfile.lock +28 -0
  83. data/gemfiles/sequel-3.14.0.gemfile +8 -0
  84. data/gemfiles/sequel-3.14.0.gemfile.lock +28 -0
  85. data/gemfiles/sequel-3.23.0.gemfile +8 -0
  86. data/gemfiles/sequel-3.23.0.gemfile.lock +28 -0
  87. data/gemfiles/sequel-3.24.0.gemfile +8 -0
  88. data/gemfiles/sequel-3.24.0.gemfile.lock +28 -0
  89. data/lib/state_machine/event.rb +13 -90
  90. data/lib/state_machine/helper_module.rb +17 -0
  91. data/lib/state_machine/integrations/active_model.rb +35 -0
  92. data/lib/state_machine/integrations/active_record.rb +41 -2
  93. data/lib/state_machine/integrations/data_mapper.rb +17 -2
  94. data/lib/state_machine/integrations/mongo_mapper.rb +34 -7
  95. data/lib/state_machine/integrations/mongoid.rb +34 -26
  96. data/lib/state_machine/integrations/mongoid/versions.rb +29 -3
  97. data/lib/state_machine/integrations/sequel.rb +22 -72
  98. data/lib/state_machine/integrations/sequel/versions.rb +87 -6
  99. data/lib/state_machine/machine.rb +279 -19
  100. data/lib/state_machine/state.rb +2 -2
  101. data/lib/state_machine/state_context.rb +133 -0
  102. data/lib/state_machine/version.rb +3 -0
  103. data/state_machine.gemspec +22 -0
  104. data/test/test_helper.rb +1 -3
  105. data/test/unit/branch_test.rb +1 -3
  106. data/test/unit/event_collection_test.rb +3 -3
  107. data/test/unit/event_test.rb +1 -3
  108. data/test/unit/helper_module_test.rb +17 -0
  109. data/test/unit/integrations/active_model_test.rb +0 -4
  110. data/test/unit/integrations/active_record_test.rb +50 -9
  111. data/test/unit/integrations/data_mapper_test.rb +267 -253
  112. data/test/unit/integrations/mongo_mapper_test.rb +47 -15
  113. data/test/unit/integrations/mongoid_test.rb +50 -8
  114. data/test/unit/integrations/sequel_test.rb +10 -6
  115. data/test/unit/machine_test.rb +206 -25
  116. data/test/unit/state_context_test.rb +421 -0
  117. data/test/unit/state_test.rb +20 -3
  118. metadata +303 -128
  119. data/lib/state_machine/condition_proxy.rb +0 -94
  120. data/test/unit/condition_proxy_test.rb +0 -328
@@ -1,19 +1,5 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
2
 
3
- # Load library
4
- require 'rubygems'
5
-
6
- if ENV['VERSION']
7
- if Gem::Version.new(ENV['VERSION']) >= Gem::Version.new('0.9.0')
8
- gem 'activesupport', '~>3.0'
9
- require 'active_support'
10
- elsif Gem::Version.new(ENV['VERSION']) <= Gem::Version.new('0.7.0') || !Gem.available?('>=0.7.0')
11
- gem 'activesupport', '~>2.3'
12
- require 'active_support'
13
- end
14
- end
15
-
16
- gem 'mongo_mapper', ENV['VERSION'] ? "=#{ENV['VERSION']}" : '>=0.5.5'
17
3
  require 'mongo_mapper'
18
4
 
19
5
  # Establish database connection
@@ -297,6 +283,33 @@ module MongoMapperTest
297
283
  end
298
284
  end
299
285
 
286
+ class MachineWithConflictingStateNameTest < BaseTestCase
287
+ def setup
288
+ require 'stringio'
289
+ @original_stderr, $stderr = $stderr, StringIO.new
290
+
291
+ @model = new_model
292
+ end
293
+
294
+ def test_should_output_warning_with_same_machine_name
295
+ @machine = StateMachine::Machine.new(@model)
296
+ @machine.state :state
297
+
298
+ assert_match /^Instance method "state\?" is already defined in .*, use generic helper instead\.\n$/, $stderr.string
299
+ end
300
+
301
+ def test_should_output_warning_with_same_machine_attribute
302
+ @machine = StateMachine::Machine.new(@model, :public_state, :attribute => :state)
303
+ @machine.state :state
304
+
305
+ assert_match /^Instance method "state\?" is already defined in .*, use generic helper instead\.\n$/, $stderr.string
306
+ end
307
+
308
+ def teardown
309
+ $stderr = @original_stderr
310
+ end
311
+ end
312
+
300
313
  class MachineWithColumnStateAttributeTest < BaseTestCase
301
314
  def setup
302
315
  @model = new_model
@@ -421,6 +434,25 @@ module MongoMapperTest
421
434
  end
422
435
  end
423
436
 
437
+ class MachineWithCustomAttributeTest < BaseTestCase
438
+ def setup
439
+ require 'stringio'
440
+ @original_stderr, $stderr = $stderr, StringIO.new
441
+
442
+ @model = new_model
443
+ @machine = StateMachine::Machine.new(@model, :public_state, :attribute => :state)
444
+ @record = @model.new
445
+ end
446
+
447
+ def test_should_not_delegate_attribute_predicate_with_different_attribute
448
+ assert_raise(ArgumentError) { @record.public_state? }
449
+ end
450
+
451
+ def teardown
452
+ $stderr = @original_stderr
453
+ end
454
+ end
455
+
424
456
  class MachineWithInitializedStateTest < BaseTestCase
425
457
  def setup
426
458
  @model = new_model
@@ -1606,6 +1638,6 @@ module MongoMapperTest
1606
1638
  end
1607
1639
  end
1608
1640
  else
1609
- $stderr.puts 'Skipping MongoMapper I18n tests. `gem install mongo_mapper` >= v0.9.0 and try again.'
1641
+ $stderr.puts 'Skipping MongoMapper I18n tests.'
1610
1642
  end
1611
1643
  end
@@ -1,9 +1,5 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
2
 
3
- # Load library
4
- require 'rubygems'
5
-
6
- gem 'mongoid', ENV['VERSION'] ? "=#{ENV['VERSION']}" : '>=2.0.0'
7
3
  require 'mongoid'
8
4
 
9
5
  # Establish database connection
@@ -273,6 +269,33 @@ module MongoidTest
273
269
  end
274
270
  end
275
271
 
272
+ class MachineWithConflictingStateNameTest < BaseTestCase
273
+ def setup
274
+ require 'stringio'
275
+ @original_stderr, $stderr = $stderr, StringIO.new
276
+
277
+ @model = new_model
278
+ end
279
+
280
+ def test_should_output_warning_with_same_machine_name
281
+ @machine = StateMachine::Machine.new(@model)
282
+ @machine.state :state
283
+
284
+ assert_match /^Instance method "state\?" is already defined in .*, use generic helper instead\.\n$/, $stderr.string
285
+ end
286
+
287
+ def test_should_output_warning_with_same_machine_attribute
288
+ @machine = StateMachine::Machine.new(@model, :public_state, :attribute => :state)
289
+ @machine.state :state
290
+
291
+ assert_match /^Instance method "state\?" is already defined in .*, use generic helper instead\.\n$/, $stderr.string
292
+ end
293
+
294
+ def teardown
295
+ $stderr = @original_stderr
296
+ end
297
+ end
298
+
276
299
  class MachineWithColumnStateAttributeTest < BaseTestCase
277
300
  def setup
278
301
  @model = new_model
@@ -403,6 +426,25 @@ module MongoidTest
403
426
  end
404
427
  end
405
428
 
429
+ class MachineWithCustomAttributeTest < BaseTestCase
430
+ def setup
431
+ require 'stringio'
432
+ @original_stderr, $stderr = $stderr, StringIO.new
433
+
434
+ @model = new_model
435
+ @machine = StateMachine::Machine.new(@model, :public_state, :attribute => :state)
436
+ @record = @model.new
437
+ end
438
+
439
+ def test_should_not_delegate_attribute_predicate_with_different_attribute
440
+ assert_raise(ArgumentError) { @record.public_state? }
441
+ end
442
+
443
+ def teardown
444
+ $stderr = @original_stderr
445
+ end
446
+ end
447
+
406
448
  class MachineWithInitializedStateTest < BaseTestCase
407
449
  def setup
408
450
  @model = new_model
@@ -538,7 +580,7 @@ module MongoidTest
538
580
  end
539
581
 
540
582
  def test_should_track_attribute_changes
541
- assert_equal %w(parked parked), @record.changes['state']
583
+ assert_equal %w(parked parked), @record.send(:attribute_change, 'state')
542
584
  end
543
585
  end
544
586
 
@@ -592,7 +634,7 @@ module MongoidTest
592
634
  end
593
635
 
594
636
  def test_should_track_attribute_changes
595
- assert_equal %w(parked parked), @record.changes['status']
637
+ assert_equal %w(parked parked), @record.send(:attribute_change, 'status')
596
638
  end
597
639
  end
598
640
 
@@ -611,12 +653,12 @@ module MongoidTest
611
653
  end
612
654
 
613
655
  def test_should_track_attribute_change
614
- assert_equal %w(parked parked), @record.changes['state']
656
+ assert_equal %w(parked parked), @record.send(:attribute_change, 'state')
615
657
  end
616
658
 
617
659
  def test_should_not_reset_changes_on_multiple_changes
618
660
  @record.state_event = 'ignite'
619
- assert_equal %w(parked parked), @record.changes['state']
661
+ assert_equal %w(parked parked), @record.send(:attribute_change, 'state')
620
662
  end
621
663
 
622
664
  def test_should_not_include_state_in_changed_attributes_if_nil
@@ -1,9 +1,5 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../../test_helper')
2
2
 
3
- # Load library
4
- require 'rubygems'
5
-
6
- gem 'sequel', ENV['VERSION'] ? "=#{ENV['VERSION']}" : '>=2.8.0'
7
3
  require 'sequel'
8
4
  require 'logger'
9
5
 
@@ -19,12 +15,20 @@ module SequelTest
19
15
  # Creates a new Sequel model (and the associated table)
20
16
  def new_model(create_table = :foo, &block)
21
17
  table_name = create_table || :foo
18
+ table_identifier = ::Sequel::SQL::Identifier.new(table_name)
19
+
20
+ if !defined?(Sequel::VERSION) || Gem::Version.new(::Sequel::VERSION) <= Gem::Version.new('3.26.0')
21
+ class << table_identifier
22
+ alias_method :original_to_s, :to_s
23
+ def to_s(*args); args.empty? ? inspect : original_to_s(*args); end
24
+ end
25
+ end
22
26
 
23
- DB.create_table!(::Sequel::SQL::Identifier.new(table_name)) do
27
+ DB.create_table!(table_identifier) do
24
28
  primary_key :id
25
29
  column :state, :string
26
30
  end if create_table
27
- model = Class.new(Sequel::Model(DB[::Sequel::SQL::Identifier.new(table_name)])) do
31
+ model = Class.new(Sequel::Model(DB[table_identifier])) do
28
32
  self.raise_on_save_failure = false
29
33
  (class << self; self; end).class_eval do
30
34
  define_method(:name) { "SequelTest::#{table_name.to_s.capitalize}" }
@@ -1068,7 +1068,7 @@ class MachineWithHelpersTest < Test::Unit::TestCase
1068
1068
  end
1069
1069
 
1070
1070
  def test_should_throw_exception_with_invalid_scope
1071
- assert_raise(RUBY_VERSION < '1.9' ? IndexError : KeyError) { @machine.define_helper(:invalid, :state) {} }
1071
+ assert_raise(RUBY_VERSION < '1.9' ? IndexError : KeyError) { @machine.define_helper(:invalid, :park) {} }
1072
1072
  end
1073
1073
  end
1074
1074
 
@@ -1081,37 +1081,37 @@ class MachineWithInstanceHelpersTest < Test::Unit::TestCase
1081
1081
 
1082
1082
  def test_should_not_redefine_existing_public_methods
1083
1083
  @klass.class_eval do
1084
- def state
1085
- 'parked'
1084
+ def park
1085
+ true
1086
1086
  end
1087
1087
  end
1088
1088
 
1089
- @machine.define_helper(:instance, :state) {}
1090
- assert_equal 'parked', @object.state
1089
+ @machine.define_helper(:instance, :park) {}
1090
+ assert_equal true, @object.park
1091
1091
  end
1092
1092
 
1093
1093
  def test_should_not_redefine_existing_protected_methods
1094
1094
  @klass.class_eval do
1095
1095
  protected
1096
- def state
1097
- 'parked'
1096
+ def park
1097
+ true
1098
1098
  end
1099
1099
  end
1100
1100
 
1101
- @machine.define_helper(:instance, :state) {}
1102
- assert_equal 'parked', @object.send(:state)
1101
+ @machine.define_helper(:instance, :park) {}
1102
+ assert_equal true, @object.send(:park)
1103
1103
  end
1104
1104
 
1105
1105
  def test_should_not_redefine_existing_private_methods
1106
1106
  @klass.class_eval do
1107
1107
  private
1108
- def state
1109
- 'parked'
1108
+ def park
1109
+ true
1110
1110
  end
1111
1111
  end
1112
1112
 
1113
- @machine.define_helper(:instance, :state) {}
1114
- assert_equal 'parked', @object.send(:state)
1113
+ @machine.define_helper(:instance, :park) {}
1114
+ assert_equal true, @object.send(:park)
1115
1115
  end
1116
1116
 
1117
1117
  def test_should_warn_if_defined_in_superclass
@@ -1213,33 +1213,45 @@ class MachineWithInstanceHelpersTest < Test::Unit::TestCase
1213
1213
  end
1214
1214
 
1215
1215
  def test_should_define_nonexistent_methods
1216
- @machine.define_helper(:instance, :state) {'parked'}
1217
- assert_equal 'parked', @object.state
1216
+ @machine.define_helper(:instance, :park) {false}
1217
+ assert_equal false, @object.park
1218
+ end
1219
+
1220
+ def test_should_warn_if_defined_multiple_times
1221
+ require 'stringio'
1222
+ @original_stderr, $stderr = $stderr, StringIO.new
1223
+
1224
+ @machine.define_helper(:instance, :park) {}
1225
+ @machine.define_helper(:instance, :park) {}
1226
+
1227
+ assert_equal "Instance method \"park\" is already defined in #{@klass} :state instance helpers, use generic helper instead.\n", $stderr.string
1228
+ ensure
1229
+ $stderr = @original_stderr
1218
1230
  end
1219
1231
 
1220
1232
  def test_should_pass_context_as_arguments
1221
1233
  helper_args = nil
1222
- @machine.define_helper(:instance, :state) {|*args| helper_args = args}
1223
- @object.state
1234
+ @machine.define_helper(:instance, :park) {|*args| helper_args = args}
1235
+ @object.park
1224
1236
  assert_equal 2, helper_args.length
1225
1237
  assert_equal [@machine, @object], helper_args
1226
1238
  end
1227
1239
 
1228
1240
  def test_should_pass_method_arguments_through
1229
1241
  helper_args = nil
1230
- @machine.define_helper(:instance, :state) {|*args| helper_args = args}
1231
- @object.state(1, 2, 3)
1242
+ @machine.define_helper(:instance, :park) {|*args| helper_args = args}
1243
+ @object.park(1, 2, 3)
1232
1244
  assert_equal 5, helper_args.length
1233
1245
  assert_equal [@machine, @object, 1, 2, 3], helper_args
1234
1246
  end
1235
1247
 
1236
1248
  def test_should_allow_string_evaluation
1237
1249
  @machine.define_helper :instance, <<-end_eval, __FILE__, __LINE__ + 1
1238
- def state
1239
- 'parked'
1250
+ def park
1251
+ false
1240
1252
  end
1241
1253
  end_eval
1242
- assert_equal 'parked', @object.state
1254
+ assert_equal false, @object.park
1243
1255
  end
1244
1256
  end
1245
1257
 
@@ -1387,6 +1399,18 @@ class MachineWithClassHelpersTest < Test::Unit::TestCase
1387
1399
  assert_equal [], @klass.states
1388
1400
  end
1389
1401
 
1402
+ def test_should_warn_if_defined_multiple_times
1403
+ require 'stringio'
1404
+ @original_stderr, $stderr = $stderr, StringIO.new
1405
+
1406
+ @machine.define_helper(:class, :states) {}
1407
+ @machine.define_helper(:class, :states) {}
1408
+
1409
+ assert_equal "Class method \"states\" is already defined in #{@klass} :state class helpers, use generic helper instead.\n", $stderr.string
1410
+ ensure
1411
+ $stderr = @original_stderr
1412
+ end
1413
+
1390
1414
  def test_should_pass_context_as_arguments
1391
1415
  helper_args = nil
1392
1416
  @machine.define_helper(:class, :states) {|*args| helper_args = args}
@@ -1808,6 +1832,40 @@ class MachineWithConflictingHelpersAfterDefinitionTest < Test::Unit::TestCase
1808
1832
  end
1809
1833
  end
1810
1834
 
1835
+ class MachineWithSuperclassConflictingHelpersAfterDefinitionTest < Test::Unit::TestCase
1836
+ def setup
1837
+ require 'stringio'
1838
+ @original_stderr, $stderr = $stderr, StringIO.new
1839
+
1840
+ @superclass = Class.new
1841
+ @klass = Class.new(@superclass)
1842
+
1843
+ @machine = StateMachine::Machine.new(@klass)
1844
+ @machine.state :parked, :idling
1845
+ @machine.event :ignite
1846
+
1847
+ @superclass.class_eval do
1848
+ def state?
1849
+ true
1850
+ end
1851
+ end
1852
+
1853
+ @object = @klass.new
1854
+ end
1855
+
1856
+ def test_should_call_superclass_attribute_predicate_without_arguments
1857
+ assert @object.state?
1858
+ end
1859
+
1860
+ def test_should_define_attribute_predicate_with_arguments
1861
+ assert !@object.state?(:parked)
1862
+ end
1863
+
1864
+ def teardown
1865
+ $stderr = @original_stderr
1866
+ end
1867
+ end
1868
+
1811
1869
  class MachineWithoutInitializeTest < Test::Unit::TestCase
1812
1870
  def setup
1813
1871
  @klass = Class.new
@@ -2288,6 +2346,86 @@ class MachineWithMultipleEventsTest < Test::Unit::TestCase
2288
2346
  end
2289
2347
  end
2290
2348
 
2349
+ class MachineWithTransitionsTest < Test::Unit::TestCase
2350
+ def setup
2351
+ @klass = Class.new
2352
+ @machine = StateMachine::Machine.new(@klass, :initial => :parked)
2353
+ end
2354
+
2355
+ def test_should_require_on_event
2356
+ exception = assert_raise(ArgumentError) { @machine.transition(:parked => :idling) }
2357
+ assert_equal 'Must specify :on event', exception.message
2358
+ end
2359
+
2360
+ def test_should_not_allow_except_to_option
2361
+ exception = assert_raise(ArgumentError) {@machine.transition(:except_to => :parked, :on => :ignite)}
2362
+ assert_equal 'Invalid key(s): except_to', exception.message
2363
+ end
2364
+
2365
+ def test_should_not_allow_except_on_option
2366
+ exception = assert_raise(ArgumentError) {@machine.transition(:except_on => :ignite, :on => :ignite)}
2367
+ assert_equal 'Invalid key(s): except_on', exception.message
2368
+ end
2369
+
2370
+ def test_should_allow_transitioning_without_a_to_state
2371
+ assert_nothing_raised {@machine.transition(:from => :parked, :on => :ignite)}
2372
+ end
2373
+
2374
+ def test_should_allow_transitioning_without_a_from_state
2375
+ assert_nothing_raised {@machine.transition(:to => :idling, :on => :ignite)}
2376
+ end
2377
+
2378
+ def test_should_allow_except_from_option
2379
+ assert_nothing_raised {@machine.transition(:except_from => :idling, :on => :ignite)}
2380
+ end
2381
+
2382
+ def test_should_allow_implicit_options
2383
+ branch = @machine.transition(:first_gear => :second_gear, :on => :shift_up)
2384
+ assert_instance_of StateMachine::Branch, branch
2385
+
2386
+ state_requirements = branch.state_requirements
2387
+ assert_equal 1, state_requirements.length
2388
+
2389
+ assert_instance_of StateMachine::WhitelistMatcher, state_requirements[0][:from]
2390
+ assert_equal [:first_gear], state_requirements[0][:from].values
2391
+ assert_instance_of StateMachine::WhitelistMatcher, state_requirements[0][:to]
2392
+ assert_equal [:second_gear], state_requirements[0][:to].values
2393
+ assert_instance_of StateMachine::WhitelistMatcher, branch.event_requirement
2394
+ assert_equal [:shift_up], branch.event_requirement.values
2395
+ end
2396
+
2397
+ def test_should_allow_multiple_implicit_options
2398
+ branch = @machine.transition(:first_gear => :second_gear, :second_gear => :third_gear, :on => :shift_up)
2399
+
2400
+ state_requirements = branch.state_requirements
2401
+ assert_equal 2, state_requirements.length
2402
+ end
2403
+
2404
+ def test_should_allow_verbose_options
2405
+ branch = @machine.transition(:from => :parked, :to => :idling, :on => :ignite)
2406
+ assert_instance_of StateMachine::Branch, branch
2407
+ end
2408
+
2409
+ def test_should_include_all_transition_states_in_machine_states
2410
+ @machine.transition(:parked => :idling, :on => :ignite)
2411
+
2412
+ assert_equal [:parked, :idling], @machine.states.map {|state| state.name}
2413
+ end
2414
+
2415
+ def test_should_include_all_transition_events_in_machine_events
2416
+ @machine.transition(:parked => :idling, :on => :ignite)
2417
+
2418
+ assert_equal [:ignite], @machine.events.map {|event| event.name}
2419
+ end
2420
+
2421
+ def test_should_allow_multiple_events
2422
+ branches = @machine.transition(:parked => :ignite, :on => [:ignite, :shift_up])
2423
+
2424
+ assert_equal 2, branches.length
2425
+ assert_equal [:ignite, :shift_up], @machine.events.map {|event| event.name}
2426
+ end
2427
+ end
2428
+
2291
2429
  class MachineWithTransitionCallbacksTest < Test::Unit::TestCase
2292
2430
  def setup
2293
2431
  @klass = Class.new do
@@ -2588,6 +2726,51 @@ class MachineWithExistingMachinesWithSameAttributesOnOwnerClassTest < Test::Unit
2588
2726
  @object.park
2589
2727
  assert_equal 'parked', @object.state
2590
2728
  end
2729
+
2730
+ def test_should_copy_new_states_to_sibling_machines
2731
+ @first_gear = @machine.state :first_gear
2732
+ assert_equal @first_gear, @second_machine.state(:first_gear)
2733
+
2734
+ @second_gear = @second_machine.state :second_gear
2735
+ assert_equal @second_gear, @machine.state(:second_gear)
2736
+ end
2737
+
2738
+ def test_should_copy_all_existing_states_to_new_machines
2739
+ third_machine = StateMachine::Machine.new(@klass, :protected_state, :attribute => :state)
2740
+
2741
+ assert_equal @machine.state(:parked), third_machine.state(:parked)
2742
+ assert_equal @machine.state(:idling), third_machine.state(:idling)
2743
+ end
2744
+ end
2745
+
2746
+ class MachineWithExistingMachinesWithSameAttributesOnOwnerSubclassTest < Test::Unit::TestCase
2747
+ def setup
2748
+ @klass = Class.new
2749
+ @machine = StateMachine::Machine.new(@klass, :initial => :parked)
2750
+ @second_machine = StateMachine::Machine.new(@klass, :public_state, :initial => :idling, :attribute => :state)
2751
+
2752
+ @subclass = Class.new(@klass)
2753
+ @object = @subclass.new
2754
+ end
2755
+
2756
+ def test_should_not_copy_sibling_machines_to_subclass_after_initialization
2757
+ @subclass.state_machine(:state) {}
2758
+ assert_equal @klass.state_machine(:public_state), @subclass.state_machine(:public_state)
2759
+ end
2760
+
2761
+ def test_should_copy_sibling_machines_to_subclass_after_new_state
2762
+ subclass_machine = @subclass.state_machine(:state) {}
2763
+ subclass_machine.state :first_gear
2764
+ assert_not_equal @klass.state_machine(:public_state), @subclass.state_machine(:public_state)
2765
+ end
2766
+
2767
+ def test_should_copy_new_states_to_sibling_machines
2768
+ subclass_machine = @subclass.state_machine(:state) {}
2769
+ @first_gear = subclass_machine.state :first_gear
2770
+
2771
+ second_subclass_machine = @subclass.state_machine(:public_state)
2772
+ assert_equal @first_gear, second_subclass_machine.state(:first_gear)
2773
+ end
2591
2774
  end
2592
2775
 
2593
2776
  class MachineWithNamespaceTest < Test::Unit::TestCase
@@ -2869,8 +3052,6 @@ end
2869
3052
 
2870
3053
  begin
2871
3054
  # Load library
2872
- require 'rubygems'
2873
- gem 'ruby-graphviz', '>=0.9.0'
2874
3055
  require 'graphviz'
2875
3056
 
2876
3057
  class MachineDrawingTest < Test::Unit::TestCase
@@ -3040,4 +3221,4 @@ begin
3040
3221
  end
3041
3222
  rescue LoadError
3042
3223
  $stderr.puts 'Skipping GraphViz StateMachine::Machine tests. `gem install ruby-graphviz` >= v0.9.0 and try again.'
3043
- end
3224
+ end unless ENV['TRAVIS']