state_machine 0.9.2 → 0.9.3

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 (36) hide show
  1. data/CHANGELOG.rdoc +10 -0
  2. data/README.rdoc +8 -0
  3. data/Rakefile +1 -1
  4. data/examples/merb-rest/view_edit.html.erb +2 -2
  5. data/examples/merb-rest/view_index.html.erb +2 -2
  6. data/examples/merb-rest/view_show.html.erb +2 -2
  7. data/examples/rails-rest/view_edit.html.erb +2 -2
  8. data/examples/rails-rest/view_index.html.erb +2 -2
  9. data/examples/rails-rest/view_show.html.erb +2 -2
  10. data/lib/state_machine.rb +34 -0
  11. data/lib/state_machine/event.rb +17 -2
  12. data/lib/state_machine/event_collection.rb +1 -1
  13. data/lib/state_machine/integrations/active_model.rb +39 -15
  14. data/lib/state_machine/integrations/active_model/locale.rb +2 -2
  15. data/lib/state_machine/integrations/active_record.rb +15 -3
  16. data/lib/state_machine/integrations/active_record/locale.rb +16 -0
  17. data/lib/state_machine/integrations/mongo_mapper.rb +16 -2
  18. data/lib/state_machine/machine.rb +53 -10
  19. data/lib/state_machine/machine_collection.rb +1 -1
  20. data/lib/state_machine/state.rb +12 -1
  21. data/lib/state_machine/transition.rb +50 -34
  22. data/test/files/en.yml +9 -0
  23. data/test/{classes → files}/switch.rb +0 -0
  24. data/test/functional/state_machine_test.rb +9 -0
  25. data/test/unit/event_collection_test.rb +5 -7
  26. data/test/unit/event_test.rb +51 -0
  27. data/test/unit/integrations/active_model_test.rb +80 -33
  28. data/test/unit/integrations/active_record_test.rb +89 -30
  29. data/test/unit/integrations/data_mapper_test.rb +25 -1
  30. data/test/unit/integrations/mongo_mapper_test.rb +40 -7
  31. data/test/unit/integrations/sequel_test.rb +25 -1
  32. data/test/unit/machine_collection_test.rb +1 -1
  33. data/test/unit/machine_test.rb +123 -4
  34. data/test/unit/state_test.rb +53 -0
  35. data/test/unit/transition_test.rb +20 -0
  36. metadata +4 -3
@@ -56,6 +56,13 @@ module ActiveRecordTest
56
56
  @notifications = []
57
57
  end
58
58
  end
59
+
60
+ (class << observer; self; end).class_eval do
61
+ define_method(:name) do
62
+ "#{model.name}Observer"
63
+ end
64
+ end
65
+
59
66
  observer.observe(model)
60
67
  observer.class_eval(&block) if block_given?
61
68
  observer
@@ -127,6 +134,18 @@ module ActiveRecordTest
127
134
  end
128
135
  end
129
136
 
137
+ class MachineWithStatesTest < BaseTestCase
138
+ def setup
139
+ @model = new_model
140
+ @machine = StateMachine::Machine.new(@model)
141
+ @machine.state :first_gear
142
+ end
143
+
144
+ def test_should_humanize_name
145
+ assert_equal 'first gear', @machine.state(:first_gear).human_name
146
+ end
147
+ end
148
+
130
149
  class MachineWithStaticInitialStateTest < BaseTestCase
131
150
  def setup
132
151
  @model = new_model do
@@ -281,6 +300,18 @@ module ActiveRecordTest
281
300
  end
282
301
  end
283
302
 
303
+ class MachineWithEventsTest < BaseTestCase
304
+ def setup
305
+ @model = new_model
306
+ @machine = StateMachine::Machine.new(@model)
307
+ @machine.event :shift_up
308
+ end
309
+
310
+ def test_should_humanize_name
311
+ assert_equal 'shift up', @machine.event(:shift_up).human_name
312
+ end
313
+ end
314
+
284
315
  class MachineWithColumnDefaultTest < BaseTestCase
285
316
  def setup
286
317
  @model = new_model do
@@ -904,7 +935,7 @@ module ActiveRecordTest
904
935
  I18n.backend = I18n::Backend::Simple.new if Object.const_defined?(:I18n)
905
936
  @record.state = 'parked'
906
937
 
907
- @machine.invalidate(@record, :state, :invalid_transition, [[:event, :park]])
938
+ @machine.invalidate(@record, :state, :invalid_transition, [[:event, 'park']])
908
939
  assert_equal ['State cannot transition via "park"'], @record.errors.full_messages
909
940
  end
910
941
 
@@ -1732,7 +1763,7 @@ module ActiveRecordTest
1732
1763
 
1733
1764
  def test_should_use_defaults
1734
1765
  I18n.backend.store_translations(:en, {
1735
- :activerecord => {:errors => {:messages => {:invalid_transition => 'cannot {{event}}'}}}
1766
+ :activerecord => {:errors => {:messages => {:invalid_transition => "cannot #{interpolation_key('event')}"}}}
1736
1767
  })
1737
1768
 
1738
1769
  machine = StateMachine::Machine.new(@model)
@@ -1741,13 +1772,13 @@ module ActiveRecordTest
1741
1772
 
1742
1773
  record = @model.new(:state => 'idling')
1743
1774
 
1744
- machine.invalidate(record, :state, :invalid_transition, [[:event, :ignite]])
1775
+ machine.invalidate(record, :state, :invalid_transition, [[:event, 'ignite']])
1745
1776
  assert_equal ['State cannot ignite'], record.errors.full_messages
1746
1777
  end
1747
1778
 
1748
1779
  def test_should_allow_customized_error_key
1749
1780
  I18n.backend.store_translations(:en, {
1750
- :activerecord => {:errors => {:messages => {:bad_transition => 'cannot {{event}}'}}}
1781
+ :activerecord => {:errors => {:messages => {:bad_transition => "cannot #{interpolation_key('event')}"}}}
1751
1782
  })
1752
1783
 
1753
1784
  machine = StateMachine::Machine.new(@model, :messages => {:invalid_transition => :bad_transition})
@@ -1755,17 +1786,17 @@ module ActiveRecordTest
1755
1786
 
1756
1787
  record = @model.new(:state => 'idling')
1757
1788
 
1758
- machine.invalidate(record, :state, :invalid_transition, [[:event, :ignite]])
1789
+ machine.invalidate(record, :state, :invalid_transition, [[:event, 'ignite']])
1759
1790
  assert_equal ['State cannot ignite'], record.errors.full_messages
1760
1791
  end
1761
1792
 
1762
1793
  def test_should_allow_customized_error_string
1763
- machine = StateMachine::Machine.new(@model, :messages => {:invalid_transition => 'cannot {{event}}'})
1794
+ machine = StateMachine::Machine.new(@model, :messages => {:invalid_transition => "cannot #{interpolation_key('event')}"})
1764
1795
  machine.state :parked, :idling
1765
1796
 
1766
1797
  record = @model.new(:state => 'idling')
1767
1798
 
1768
- machine.invalidate(record, :state, :invalid_transition, [[:event, :ignite]])
1799
+ machine.invalidate(record, :state, :invalid_transition, [[:event, 'ignite']])
1769
1800
  assert_equal ['State cannot ignite'], record.errors.full_messages
1770
1801
  end
1771
1802
 
@@ -1774,11 +1805,10 @@ module ActiveRecordTest
1774
1805
  :activerecord => {:state_machines => {:'active_record_test/foo' => {:state => {:states => {:parked => 'shutdown'}}}}}
1775
1806
  })
1776
1807
 
1777
- machine = StateMachine::Machine.new(@model, :initial => :parked)
1778
- record = @model.new
1808
+ machine = StateMachine::Machine.new(@model)
1809
+ machine.state :parked
1779
1810
 
1780
- machine.invalidate(record, :event, :invalid_event, [[:state, :parked]])
1781
- assert_equal ['State event cannot transition when shutdown'], record.errors.full_messages
1811
+ assert_equal 'shutdown', machine.state(:parked).human_name
1782
1812
  end
1783
1813
 
1784
1814
  def test_should_allow_customized_state_key_scoped_to_machine
@@ -1786,11 +1816,10 @@ module ActiveRecordTest
1786
1816
  :activerecord => {:state_machines => {:state => {:states => {:parked => 'shutdown'}}}}
1787
1817
  })
1788
1818
 
1789
- machine = StateMachine::Machine.new(@model, :initial => :parked)
1790
- record = @model.new
1819
+ machine = StateMachine::Machine.new(@model)
1820
+ machine.state :parked
1791
1821
 
1792
- machine.invalidate(record, :event, :invalid_event, [[:state, :parked]])
1793
- assert_equal ['State event cannot transition when shutdown'], record.errors.full_messages
1822
+ assert_equal 'shutdown', machine.state(:parked).human_name
1794
1823
  end
1795
1824
 
1796
1825
  def test_should_allow_customized_state_key_unscoped
@@ -1798,11 +1827,10 @@ module ActiveRecordTest
1798
1827
  :activerecord => {:state_machines => {:states => {:parked => 'shutdown'}}}
1799
1828
  })
1800
1829
 
1801
- machine = StateMachine::Machine.new(@model, :initial => :parked)
1802
- record = @model.new
1830
+ machine = StateMachine::Machine.new(@model)
1831
+ machine.state :parked
1803
1832
 
1804
- machine.invalidate(record, :event, :invalid_event, [[:state, :parked]])
1805
- assert_equal ['State event cannot transition when shutdown'], record.errors.full_messages
1833
+ assert_equal 'shutdown', machine.state(:parked).human_name
1806
1834
  end
1807
1835
 
1808
1836
  def test_should_allow_customized_event_key_scoped_to_class_and_machine
@@ -1812,10 +1840,8 @@ module ActiveRecordTest
1812
1840
 
1813
1841
  machine = StateMachine::Machine.new(@model)
1814
1842
  machine.event :park
1815
- record = @model.new
1816
1843
 
1817
- machine.invalidate(record, :state, :invalid_transition, [[:event, :park]])
1818
- assert_equal ['State cannot transition via "stop"'], record.errors.full_messages
1844
+ assert_equal 'stop', machine.event(:park).human_name
1819
1845
  end
1820
1846
 
1821
1847
  def test_should_allow_customized_event_key_scoped_to_machine
@@ -1825,10 +1851,8 @@ module ActiveRecordTest
1825
1851
 
1826
1852
  machine = StateMachine::Machine.new(@model)
1827
1853
  machine.event :park
1828
- record = @model.new
1829
1854
 
1830
- machine.invalidate(record, :state, :invalid_transition, [[:event, :park]])
1831
- assert_equal ['State cannot transition via "stop"'], record.errors.full_messages
1855
+ assert_equal 'stop', machine.event(:park).human_name
1832
1856
  end
1833
1857
 
1834
1858
  def test_should_allow_customized_event_key_unscoped
@@ -1838,20 +1862,55 @@ module ActiveRecordTest
1838
1862
 
1839
1863
  machine = StateMachine::Machine.new(@model)
1840
1864
  machine.event :park
1841
- record = @model.new
1842
1865
 
1843
- machine.invalidate(record, :state, :invalid_transition, [[:event, :park]])
1844
- assert_equal ['State cannot transition via "stop"'], record.errors.full_messages
1866
+ assert_equal 'stop', machine.event(:park).human_name
1845
1867
  end
1846
1868
 
1847
1869
  def test_should_only_add_locale_once_in_load_path
1848
- assert_equal 1, I18n.load_path.select {|path| path =~ %r{state_machine/integrations/active_record/locale\.rb$}}.length
1870
+ assert_equal 1, I18n.load_path.select {|path| path =~ %r{active_record/locale\.rb$}}.length
1849
1871
 
1850
1872
  # Create another ActiveRecord model that will triger the i18n feature
1851
1873
  new_model
1852
1874
 
1853
- assert_equal 1, I18n.load_path.select {|path| path =~ %r{state_machine/integrations/active_record/locale\.rb$}}.length
1875
+ assert_equal 1, I18n.load_path.select {|path| path =~ %r{active_record/locale\.rb$}}.length
1876
+ end
1877
+
1878
+ def test_should_add_locale_to_beginning_of_load_path
1879
+ @original_load_path = I18n.load_path
1880
+ I18n.backend = I18n::Backend::Simple.new
1881
+
1882
+ app_locale = File.dirname(__FILE__) + '/../../files/en.yml'
1883
+ default_locale = File.dirname(__FILE__) + '/../../../lib/state_machine/integrations/active_record/locale.rb'
1884
+ I18n.load_path = [app_locale]
1885
+
1886
+ StateMachine::Machine.new(@model)
1887
+
1888
+ assert_equal [default_locale, app_locale].map {|path| File.expand_path(path)}, I18n.load_path.map {|path| File.expand_path(path)}
1889
+ ensure
1890
+ I18n.load_path = @original_load_path
1891
+ end
1892
+
1893
+ def test_should_prefer_other_locales_first
1894
+ @original_load_path = I18n.load_path
1895
+ I18n.backend = I18n::Backend::Simple.new
1896
+ I18n.load_path = [File.dirname(__FILE__) + '/../../files/en.yml']
1897
+
1898
+ machine = StateMachine::Machine.new(@model)
1899
+ machine.state :parked, :idling
1900
+ machine.event :ignite
1901
+
1902
+ record = @model.new(:state => 'idling')
1903
+
1904
+ machine.invalidate(record, :state, :invalid_transition, [[:event, 'ignite']])
1905
+ assert_equal ['State cannot transition'], record.errors.full_messages
1906
+ ensure
1907
+ I18n.load_path = @original_load_path
1854
1908
  end
1909
+
1910
+ private
1911
+ def interpolation_key(key)
1912
+ !defined?(I18n::VERSION) || I18n::VERSION < '0.4.0' ? "{{#{key}}}" : "%{#{key}}"
1913
+ end
1855
1914
  end
1856
1915
  else
1857
1916
  $stderr.puts 'Skipping ActiveRecord I18n tests. `gem install active_record` >= v2.2.0 and try again.'
@@ -114,6 +114,18 @@ module DataMapperTest
114
114
  end
115
115
  end
116
116
 
117
+ class MachineWithStatesTest < BaseTestCase
118
+ def setup
119
+ @resource = new_resource
120
+ @machine = StateMachine::Machine.new(@resource)
121
+ @machine.state :first_gear
122
+ end
123
+
124
+ def test_should_humanize_name
125
+ assert_equal 'first gear', @machine.state(:first_gear).human_name
126
+ end
127
+ end
128
+
117
129
  class MachineWithStaticInitialStateTest < BaseTestCase
118
130
  def setup
119
131
  @resource = new_resource do
@@ -254,6 +266,18 @@ module DataMapperTest
254
266
  end
255
267
  end
256
268
 
269
+ class MachineWithEventsTest < BaseTestCase
270
+ def setup
271
+ @resource = new_resource
272
+ @machine = StateMachine::Machine.new(@resource)
273
+ @machine.event :shift_up
274
+ end
275
+
276
+ def test_should_humanize_name
277
+ assert_equal 'shift up', @machine.event(:shift_up).human_name
278
+ end
279
+ end
280
+
257
281
  class MachineWithColumnDefaultTest < BaseTestCase
258
282
  def setup
259
283
  @resource = new_resource do
@@ -896,7 +920,7 @@ module DataMapperTest
896
920
  def test_should_invalidate_using_errors
897
921
  @record.state = 'parked'
898
922
 
899
- @machine.invalidate(@record, :state, :invalid_transition, [[:event, :park]])
923
+ @machine.invalidate(@record, :state, :invalid_transition, [[:event, 'park']])
900
924
  assert_equal ['cannot transition via "park"'], @record.errors.on(:state)
901
925
  end
902
926
 
@@ -87,6 +87,18 @@ module MongoMapperTest
87
87
  end
88
88
  end
89
89
 
90
+ class MachineWithStatesTest < BaseTestCase
91
+ def setup
92
+ @model = new_model
93
+ @machine = StateMachine::Machine.new(@model)
94
+ @machine.state :first_gear
95
+ end
96
+
97
+ def test_should_humanize_name
98
+ assert_equal 'first gear', @machine.state(:first_gear).human_name
99
+ end
100
+ end
101
+
90
102
  class MachineWithStaticInitialStateTest < BaseTestCase
91
103
  def setup
92
104
  @model = new_model do
@@ -221,6 +233,18 @@ module MongoMapperTest
221
233
  end
222
234
  end
223
235
 
236
+ class MachineWithEventsTest < BaseTestCase
237
+ def setup
238
+ @model = new_model
239
+ @machine = StateMachine::Machine.new(@model)
240
+ @machine.event :shift_up
241
+ end
242
+
243
+ def test_should_humanize_name
244
+ assert_equal 'shift up', @machine.event(:shift_up).human_name
245
+ end
246
+ end
247
+
224
248
  class MachineWithColumnDefaultTest < BaseTestCase
225
249
  def setup
226
250
  @model = new_model do
@@ -792,7 +816,7 @@ module MongoMapperTest
792
816
  def test_should_invalidate_using_errors
793
817
  @record.state = 'parked'
794
818
 
795
- @machine.invalidate(@record, :state, :invalid_transition, [[:event, :park]])
819
+ @machine.invalidate(@record, :state, :invalid_transition, [[:event, 'park']])
796
820
  assert_equal ['State cannot transition via "park"'], @record.errors.full_messages
797
821
  end
798
822
 
@@ -1268,7 +1292,7 @@ module MongoMapperTest
1268
1292
  parked = @model.create :state => 'parked'
1269
1293
  idling = @model.create :state => 'idling'
1270
1294
 
1271
- assert_equal [parked], @model.with_state(:parked)
1295
+ assert_equal [parked], @model.with_state(:parked).to_a
1272
1296
  end
1273
1297
 
1274
1298
  def test_should_create_plural_with_scope
@@ -1279,7 +1303,7 @@ module MongoMapperTest
1279
1303
  parked = @model.create :state => 'parked'
1280
1304
  idling = @model.create :state => 'idling'
1281
1305
 
1282
- assert_equal [parked, idling], @model.with_states(:parked, :idling)
1306
+ assert_equal [parked, idling], @model.with_states(:parked, :idling).to_a
1283
1307
  end
1284
1308
 
1285
1309
  def test_should_create_singular_without_scope
@@ -1290,7 +1314,7 @@ module MongoMapperTest
1290
1314
  parked = @model.create :state => 'parked'
1291
1315
  idling = @model.create :state => 'idling'
1292
1316
 
1293
- assert_equal [parked], @model.without_state(:idling)
1317
+ assert_equal [parked], @model.without_state(:idling).to_a
1294
1318
  end
1295
1319
 
1296
1320
  def test_should_create_plural_without_scope
@@ -1302,7 +1326,16 @@ module MongoMapperTest
1302
1326
  idling = @model.create :state => 'idling'
1303
1327
  first_gear = @model.create :state => 'first_gear'
1304
1328
 
1305
- assert_equal [parked, idling], @model.without_states(:first_gear)
1329
+ assert_equal [parked, idling], @model.without_states(:first_gear).to_a
1330
+ end
1331
+
1332
+ if defined?(MongoMapper::Version) && MongoMapper::Version >= '0.8.0'
1333
+ def test_should_allow_chaining_scopes
1334
+ parked = @model.create :state => 'parked'
1335
+ idling = @model.create :state => 'idling'
1336
+
1337
+ assert_equal [idling], @model.without_state(:parked).with_state(:idling).all
1338
+ end
1306
1339
  end
1307
1340
  end
1308
1341
 
@@ -1320,7 +1353,7 @@ module MongoMapperTest
1320
1353
  parked = @subclass.create :state => 'parked'
1321
1354
  idling = @subclass.create :state => 'idling'
1322
1355
 
1323
- assert_equal [parked, idling], @subclass.with_states(:parked, :idling)
1356
+ assert_equal [parked, idling], @subclass.with_states(:parked, :idling).to_a
1324
1357
  end
1325
1358
 
1326
1359
  def test_should_only_include_records_without_subclass_states_in_without_scope
@@ -1328,7 +1361,7 @@ module MongoMapperTest
1328
1361
  idling = @subclass.create :state => 'idling'
1329
1362
  first_gear = @subclass.create :state => 'first_gear'
1330
1363
 
1331
- assert_equal [parked, idling], @subclass.without_states(:first_gear)
1364
+ assert_equal [parked, idling], @subclass.without_states(:first_gear).to_a
1332
1365
  end
1333
1366
  end
1334
1367
 
@@ -92,6 +92,18 @@ module SequelTest
92
92
  end
93
93
  end
94
94
 
95
+ class MachineWithStatesTest < BaseTestCase
96
+ def setup
97
+ @model = new_model
98
+ @machine = StateMachine::Machine.new(@model)
99
+ @machine.state :first_gear
100
+ end
101
+
102
+ def test_should_humanize_name
103
+ assert_equal 'first gear', @machine.state(:first_gear).human_name
104
+ end
105
+ end
106
+
95
107
  class MachineWithStaticInitialStateTest < BaseTestCase
96
108
  def setup
97
109
  @model = new_model do
@@ -259,6 +271,18 @@ module SequelTest
259
271
  end
260
272
  end
261
273
 
274
+ class MachineWithEventsTest < BaseTestCase
275
+ def setup
276
+ @model = new_model
277
+ @machine = StateMachine::Machine.new(@model)
278
+ @machine.event :shift_up
279
+ end
280
+
281
+ def test_should_humanize_name
282
+ assert_equal 'shift up', @machine.event(:shift_up).human_name
283
+ end
284
+ end
285
+
262
286
  class MachineWithColumnDefaultTest < BaseTestCase
263
287
  def setup
264
288
  @model = new_model
@@ -861,7 +885,7 @@ module SequelTest
861
885
  def test_should_invalidate_using_errors
862
886
  @record.state = 'parked'
863
887
 
864
- @machine.invalidate(@record, :state, :invalid_transition, [[:event, :park]])
888
+ @machine.invalidate(@record, :state, :invalid_transition, [[:event, 'park']])
865
889
  assert_equal ['cannot transition via "park"'], @record.errors.on(:state)
866
890
  end
867
891
 
@@ -285,7 +285,7 @@ class MachineCollectionFireWithValidationsTest < Test::Unit::TestCase
285
285
  @object.alarm_state = 'off'
286
286
 
287
287
  assert !@machines.fire_events(@object, :ignite, :disable_alarm)
288
- assert_equal ['cannot transition via "ignite"', 'cannot transition via "disable_alarm"'], @object.errors
288
+ assert_equal ['cannot transition via "ignite"', 'cannot transition via "disable"'], @object.errors
289
289
  end
290
290
 
291
291
  def teardown
@@ -129,6 +129,14 @@ class MachineByDefaultTest < Test::Unit::TestCase
129
129
  assert !@object.respond_to?(:state_event_transition=)
130
130
  end
131
131
 
132
+ def test_should_define_a_human_attribute_name_reader_for_the_attribute
133
+ assert @klass.respond_to?(:human_state_name)
134
+ end
135
+
136
+ def test_should_define_a_human_event_name_reader_for_the_attribute
137
+ assert @klass.respond_to?(:human_state_event_name)
138
+ end
139
+
132
140
  def test_should_not_define_singular_with_scope
133
141
  assert !@klass.respond_to?(:with_state)
134
142
  end
@@ -201,6 +209,14 @@ class MachineWithCustomNameTest < Test::Unit::TestCase
201
209
  def test_should_define_a_transition_reader_for_the_attribute
202
210
  assert @object.respond_to?(:status_transitions)
203
211
  end
212
+
213
+ def test_should_define_a_human_attribute_name_reader_for_the_attribute
214
+ assert @klass.respond_to?(:human_status_name)
215
+ end
216
+
217
+ def test_should_define_a_human_event_name_reader_for_the_attribute
218
+ assert @klass.respond_to?(:human_status_event_name)
219
+ end
204
220
  end
205
221
 
206
222
  class MachineWithStaticInitialStateTest < Test::Unit::TestCase
@@ -367,7 +383,7 @@ class MachineWithoutIntegrationTest < Test::Unit::TestCase
367
383
  end
368
384
 
369
385
  def test_invalidation_should_do_nothing
370
- assert_nil @machine.invalidate(@object, :state, :invalid_transition, [[:event, :park]])
386
+ assert_nil @machine.invalidate(@object, :state, :invalid_transition, [[:event, 'park']])
371
387
  end
372
388
 
373
389
  def test_reset_should_do_nothing
@@ -754,7 +770,7 @@ class MachineWithCustomInvalidationTest < Test::Unit::TestCase
754
770
  end
755
771
 
756
772
  def test_use_custom_message
757
- @machine.invalidate(@object, :state, :invalid_transition, [[:event, :park]])
773
+ @machine.invalidate(@object, :state, :invalid_transition, [[:event, 'park']])
758
774
  assert_equal 'cannot park', @object.error
759
775
  end
760
776
 
@@ -1017,6 +1033,14 @@ class MachineWithConflictingHelpersTest < Test::Unit::TestCase
1017
1033
  :without_states
1018
1034
  end
1019
1035
 
1036
+ def self.human_state_name
1037
+ :human_state_name
1038
+ end
1039
+
1040
+ def self.human_state_event_name
1041
+ :human_state_event_name
1042
+ end
1043
+
1020
1044
  attr_accessor :status
1021
1045
 
1022
1046
  def state
@@ -1035,6 +1059,10 @@ class MachineWithConflictingHelpersTest < Test::Unit::TestCase
1035
1059
  :parked
1036
1060
  end
1037
1061
 
1062
+ def human_state_name
1063
+ 'parked'
1064
+ end
1065
+
1038
1066
  def state_events
1039
1067
  [:ignite]
1040
1068
  end
@@ -1056,6 +1084,7 @@ class MachineWithConflictingHelpersTest < Test::Unit::TestCase
1056
1084
 
1057
1085
  @machine = StateMachine::Machine.new(@klass, :integration => :custom)
1058
1086
  @machine.state :parked, :idling
1087
+ @machine.event :ignite
1059
1088
  @object = @klass.new
1060
1089
  end
1061
1090
 
@@ -1075,6 +1104,14 @@ class MachineWithConflictingHelpersTest < Test::Unit::TestCase
1075
1104
  assert_equal :without_states, @klass.without_states
1076
1105
  end
1077
1106
 
1107
+ def test_should_not_redefine_human_attribute_name_reader
1108
+ assert_equal :human_state_name, @klass.human_state_name
1109
+ end
1110
+
1111
+ def test_should_not_redefine_human_event_name_reader
1112
+ assert_equal :human_state_event_name, @klass.human_state_event_name
1113
+ end
1114
+
1078
1115
  def test_should_not_redefine_attribute_writer
1079
1116
  assert_equal 'parked', @object.state
1080
1117
  end
@@ -1092,6 +1129,10 @@ class MachineWithConflictingHelpersTest < Test::Unit::TestCase
1092
1129
  assert_equal :parked, @object.state_name
1093
1130
  end
1094
1131
 
1132
+ def test_should_not_redefine_attribute_human_name_reader
1133
+ assert_equal 'parked', @object.human_state_name
1134
+ end
1135
+
1095
1136
  def test_should_not_redefine_attribute_events_reader
1096
1137
  assert_equal [:ignite], @object.state_events
1097
1138
  end
@@ -1118,6 +1159,14 @@ class MachineWithConflictingHelpersTest < Test::Unit::TestCase
1118
1159
  super == []
1119
1160
  end
1120
1161
 
1162
+ def self.human_state_name(state)
1163
+ super == 'parked'
1164
+ end
1165
+
1166
+ def self.human_state_event_name(event)
1167
+ super == 'ignite'
1168
+ end
1169
+
1121
1170
  attr_accessor :status
1122
1171
 
1123
1172
  def state
@@ -1137,6 +1186,10 @@ class MachineWithConflictingHelpersTest < Test::Unit::TestCase
1137
1186
  super == :parked ? 1 : 0
1138
1187
  end
1139
1188
 
1189
+ def human_state_name
1190
+ super == 'parked' ? 1 : 0
1191
+ end
1192
+
1140
1193
  def state_events
1141
1194
  super == []
1142
1195
  end
@@ -1150,12 +1203,15 @@ class MachineWithConflictingHelpersTest < Test::Unit::TestCase
1150
1203
  assert_equal true, @klass.with_states
1151
1204
  assert_equal true, @klass.without_state
1152
1205
  assert_equal true, @klass.without_states
1206
+ assert_equal true, @klass.human_state_name(:parked)
1207
+ assert_equal true, @klass.human_state_event_name(:ignite)
1153
1208
 
1154
1209
  assert_equal 'parked', @object.state
1155
1210
  @object.state = 'idling'
1156
1211
  assert_equal 'idling', @object.status
1157
1212
  assert_equal 0, @object.state?(:parked)
1158
1213
  assert_equal 0, @object.state_name
1214
+ assert_equal 0, @object.human_state_name
1159
1215
  assert_equal true, @object.state_events
1160
1216
  assert_equal true, @object.state_transitions
1161
1217
  end
@@ -1316,6 +1372,15 @@ class MachineWithStatesTest < Test::Unit::TestCase
1316
1372
  assert_equal @parked, @machine.states['parked', :value]
1317
1373
  end
1318
1374
 
1375
+ def test_should_allow_human_state_name_lookup
1376
+ assert_equal 'parked', @klass.human_state_name(:parked)
1377
+ end
1378
+
1379
+ def test_should_raise_exception_on_invalid_human_state_name_lookup
1380
+ exception = assert_raise(IndexError) {@klass.human_state_name(:invalid)}
1381
+ assert_equal ':invalid is an invalid name', exception.message
1382
+ end
1383
+
1319
1384
  def test_should_use_stringified_name_for_value
1320
1385
  assert_equal 'parked', @parked.value
1321
1386
  end
@@ -1349,6 +1414,22 @@ class MachineWithStatesWithCustomValuesTest < Test::Unit::TestCase
1349
1414
  end
1350
1415
  end
1351
1416
 
1417
+ class MachineWithStatesWithCustomHumanNamesTest < Test::Unit::TestCase
1418
+ def setup
1419
+ @klass = Class.new
1420
+ @machine = StateMachine::Machine.new(@klass)
1421
+ @state = @machine.state :parked, :human_name => 'stopped'
1422
+ end
1423
+
1424
+ def test_should_use_custom_human_name
1425
+ assert_equal 'stopped', @state.human_name
1426
+ end
1427
+
1428
+ def test_should_allow_human_state_name_lookup
1429
+ assert_equal 'stopped', @klass.human_state_name(:parked)
1430
+ end
1431
+ end
1432
+
1352
1433
  class MachineWithStatesWithRuntimeDependenciesTest < Test::Unit::TestCase
1353
1434
  def setup
1354
1435
  @klass = Class.new
@@ -1501,6 +1582,16 @@ class MachineWithEventsTest < Test::Unit::TestCase
1501
1582
  event = @machine.event(:ignite)
1502
1583
  assert_equal [event], @machine.events.to_a
1503
1584
  end
1585
+
1586
+ def test_should_allow_human_state_name_lookup
1587
+ @machine.event(:ignite)
1588
+ assert_equal 'ignite', @klass.human_state_event_name(:ignite)
1589
+ end
1590
+
1591
+ def test_should_raise_exception_on_invalid_human_state_event_name_lookup
1592
+ exception = assert_raise(IndexError) {@klass.human_state_event_name(:invalid)}
1593
+ assert_equal ':invalid is an invalid name', exception.message
1594
+ end
1504
1595
  end
1505
1596
 
1506
1597
  class MachineWithExistingEventTest < Test::Unit::TestCase
@@ -1519,6 +1610,22 @@ class MachineWithExistingEventTest < Test::Unit::TestCase
1519
1610
  end
1520
1611
  end
1521
1612
 
1613
+ class MachineWithEventsWithCustomHumanNamesTest < Test::Unit::TestCase
1614
+ def setup
1615
+ @klass = Class.new
1616
+ @machine = StateMachine::Machine.new(@klass)
1617
+ @event = @machine.event(:ignite, :human_name => 'start')
1618
+ end
1619
+
1620
+ def test_should_use_custom_human_name
1621
+ assert_equal 'start', @event.human_name
1622
+ end
1623
+
1624
+ def test_should_allow_human_state_name_lookup
1625
+ assert_equal 'start', @klass.human_state_event_name(:ignite)
1626
+ end
1627
+ end
1628
+
1522
1629
  class MachineWithEventsWithTransitionsTest < Test::Unit::TestCase
1523
1630
  def setup
1524
1631
  @klass = Class.new
@@ -1882,6 +1989,10 @@ class MachineWithCustomAttributeTest < Test::Unit::TestCase
1882
1989
  assert @object.respond_to?(:state_name)
1883
1990
  end
1884
1991
 
1992
+ def test_should_define_a_human_name_reader_for_the_attribute
1993
+ assert @object.respond_to?(:state_name)
1994
+ end
1995
+
1885
1996
  def test_should_define_an_event_reader_for_the_attribute
1886
1997
  assert @object.respond_to?(:state_events)
1887
1998
  end
@@ -1890,6 +2001,14 @@ class MachineWithCustomAttributeTest < Test::Unit::TestCase
1890
2001
  assert @object.respond_to?(:state_transitions)
1891
2002
  end
1892
2003
 
2004
+ def test_should_define_a_human_attribute_name_reader
2005
+ assert @klass.respond_to?(:human_state_name)
2006
+ end
2007
+
2008
+ def test_should_define_a_human_event_name_reader
2009
+ assert @klass.respond_to?(:human_state_event_name)
2010
+ end
2011
+
1893
2012
  def test_should_define_singular_with_scope
1894
2013
  assert @klass.respond_to?(:with_state)
1895
2014
  end
@@ -2212,14 +2331,14 @@ begin
2212
2331
  end
2213
2332
 
2214
2333
  def test_should_load_files
2215
- StateMachine::Machine.draw('Switch', :file => "#{File.dirname(__FILE__)}/../classes/switch.rb")
2334
+ StateMachine::Machine.draw('Switch', :file => "#{File.dirname(__FILE__)}/../files/switch.rb")
2216
2335
  assert defined?(::Switch)
2217
2336
  ensure
2218
2337
  FileUtils.rm('./Switch_state.png')
2219
2338
  end
2220
2339
 
2221
2340
  def test_should_allow_path_and_format_to_be_customized
2222
- StateMachine::Machine.draw('Switch', :file => "#{File.dirname(__FILE__)}/../classes/switch.rb", :path => "#{File.dirname(__FILE__)}/", :format => 'jpg')
2341
+ StateMachine::Machine.draw('Switch', :file => "#{File.dirname(__FILE__)}/../files/switch.rb", :path => "#{File.dirname(__FILE__)}/", :format => 'jpg')
2223
2342
  assert File.exist?("#{File.dirname(__FILE__)}/Switch_state.jpg")
2224
2343
  ensure
2225
2344
  FileUtils.rm("#{File.dirname(__FILE__)}/Switch_state.jpg")