enum_state_machine 0.0.2 → 0.1.0

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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -12
  3. data/.ruby-version +1 -1
  4. data/.ruby-version.orig +5 -0
  5. data/Gemfile +0 -1
  6. data/Rakefile +0 -18
  7. data/enum_state_machine.gemspec +35 -0
  8. data/enum_state_machine.gemspec.orig +43 -0
  9. data/lib/enum_state_machine/assertions.rb +36 -0
  10. data/lib/enum_state_machine/branch.rb +225 -0
  11. data/lib/enum_state_machine/callback.rb +232 -0
  12. data/lib/enum_state_machine/core.rb +12 -0
  13. data/lib/enum_state_machine/core_ext/class/state_machine.rb +5 -0
  14. data/lib/enum_state_machine/core_ext.rb +2 -0
  15. data/lib/enum_state_machine/error.rb +13 -0
  16. data/lib/enum_state_machine/eval_helpers.rb +87 -0
  17. data/lib/enum_state_machine/event.rb +257 -0
  18. data/lib/enum_state_machine/event_collection.rb +141 -0
  19. data/lib/enum_state_machine/extensions.rb +149 -0
  20. data/lib/enum_state_machine/graph.rb +93 -0
  21. data/lib/enum_state_machine/helper_module.rb +17 -0
  22. data/lib/enum_state_machine/initializers/rails.rb +22 -0
  23. data/lib/enum_state_machine/initializers.rb +4 -0
  24. data/lib/enum_state_machine/integrations/active_model/locale.rb +11 -0
  25. data/lib/enum_state_machine/integrations/active_model/observer.rb +33 -0
  26. data/lib/enum_state_machine/integrations/active_model/observer_update.rb +42 -0
  27. data/lib/enum_state_machine/integrations/active_model/versions.rb +31 -0
  28. data/lib/enum_state_machine/integrations/active_model.rb +585 -0
  29. data/lib/enum_state_machine/integrations/active_record/locale.rb +20 -0
  30. data/lib/enum_state_machine/integrations/active_record/versions.rb +123 -0
  31. data/lib/enum_state_machine/integrations/active_record.rb +548 -0
  32. data/lib/enum_state_machine/integrations/base.rb +100 -0
  33. data/lib/enum_state_machine/integrations.rb +97 -0
  34. data/lib/enum_state_machine/machine.rb +2292 -0
  35. data/lib/enum_state_machine/machine_collection.rb +86 -0
  36. data/lib/enum_state_machine/macro_methods.rb +518 -0
  37. data/lib/enum_state_machine/matcher.rb +123 -0
  38. data/lib/enum_state_machine/matcher_helpers.rb +54 -0
  39. data/lib/enum_state_machine/node_collection.rb +222 -0
  40. data/lib/enum_state_machine/path.rb +120 -0
  41. data/lib/enum_state_machine/path_collection.rb +90 -0
  42. data/lib/enum_state_machine/state.rb +297 -0
  43. data/lib/enum_state_machine/state_collection.rb +112 -0
  44. data/lib/enum_state_machine/state_context.rb +138 -0
  45. data/lib/enum_state_machine/state_enum.rb +23 -0
  46. data/lib/enum_state_machine/transition.rb +470 -0
  47. data/lib/enum_state_machine/transition_collection.rb +245 -0
  48. data/lib/enum_state_machine/version.rb +3 -0
  49. data/lib/enum_state_machine/yard/handlers/base.rb +32 -0
  50. data/lib/enum_state_machine/yard/handlers/event.rb +25 -0
  51. data/lib/enum_state_machine/yard/handlers/machine.rb +344 -0
  52. data/lib/enum_state_machine/yard/handlers/state.rb +25 -0
  53. data/lib/enum_state_machine/yard/handlers/transition.rb +47 -0
  54. data/lib/enum_state_machine/yard/handlers.rb +12 -0
  55. data/lib/enum_state_machine/yard/templates/default/class/html/setup.rb +30 -0
  56. data/lib/enum_state_machine/yard/templates/default/class/html/state_machines.erb +12 -0
  57. data/lib/enum_state_machine/yard/templates.rb +3 -0
  58. data/lib/enum_state_machine/yard.rb +8 -0
  59. data/lib/enum_state_machine.rb +9 -0
  60. data/lib/tasks/enum_state_machine.rake +1 -0
  61. data/lib/tasks/enum_state_machine.rb +24 -0
  62. data/lib/yard-enum_state_machine.rb +2 -0
  63. data/test/functional/state_machine_test.rb +1066 -0
  64. data/test/unit/graph_test.rb +9 -5
  65. data/test/unit/integrations/active_model_test.rb +1245 -0
  66. data/test/unit/integrations/active_record_test.rb +2551 -0
  67. data/test/unit/integrations/base_test.rb +104 -0
  68. data/test/unit/integrations_test.rb +71 -0
  69. data/test/unit/invalid_event_test.rb +20 -0
  70. data/test/unit/invalid_parallel_transition_test.rb +18 -0
  71. data/test/unit/invalid_transition_test.rb +115 -0
  72. data/test/unit/machine_collection_test.rb +603 -0
  73. data/test/unit/machine_test.rb +3395 -0
  74. data/test/unit/state_machine_test.rb +31 -0
  75. metadata +212 -44
  76. data/Appraisals +0 -28
  77. data/gemfiles/active_model_4.0.4.gemfile +0 -9
  78. data/gemfiles/active_model_4.0.4.gemfile.lock +0 -51
  79. data/gemfiles/active_record_4.0.4.gemfile +0 -11
  80. data/gemfiles/active_record_4.0.4.gemfile.lock +0 -61
  81. data/gemfiles/default.gemfile +0 -7
  82. data/gemfiles/default.gemfile.lock +0 -27
  83. data/gemfiles/graphviz_1.0.9.gemfile +0 -7
  84. data/gemfiles/graphviz_1.0.9.gemfile.lock +0 -30
@@ -0,0 +1,603 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class MachineCollectionByDefaultTest < Test::Unit::TestCase
4
+ def setup
5
+ @machines = EnumStateMachine::MachineCollection.new
6
+ end
7
+
8
+ def test_should_not_have_any_machines
9
+ assert @machines.empty?
10
+ end
11
+ end
12
+
13
+ class MachineCollectionStateInitializationTest < Test::Unit::TestCase
14
+ def setup
15
+ @machines = EnumStateMachine::MachineCollection.new
16
+
17
+ @klass = Class.new
18
+
19
+ @machines[:state] = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked)
20
+ @machines[:alarm_state] = EnumStateMachine::Machine.new(@klass, :alarm_state, :initial => lambda {|object| :active})
21
+ @machines[:alarm_state].state :active, :value => lambda {'active'}
22
+
23
+ # Prevent the auto-initialization hook from firing
24
+ @klass.class_eval do
25
+ def initialize
26
+ end
27
+ end
28
+
29
+ @object = @klass.new
30
+ @object.state = nil
31
+ @object.alarm_state = nil
32
+ end
33
+
34
+ def test_should_raise_exception_if_invalid_option_specified
35
+ assert_raise(ArgumentError) {@machines.initialize_states(@object, :invalid => true)}
36
+ end
37
+
38
+ def test_should_only_initialize_static_states_prior_to_block
39
+ @machines.initialize_states(@object) do
40
+ @state_in_block = @object.state
41
+ @alarm_state_in_block = @object.alarm_state
42
+ end
43
+
44
+ assert_equal 'parked', @state_in_block
45
+ assert_nil @alarm_state_in_block
46
+ end
47
+
48
+ def test_should_only_initialize_dynamic_states_after_block
49
+ @machines.initialize_states(@object) do
50
+ @alarm_state_in_block = @object.alarm_state
51
+ end
52
+
53
+ assert_nil @alarm_state_in_block
54
+ assert_equal 'active', @object.alarm_state
55
+ end
56
+
57
+ def test_should_initialize_all_states_without_block
58
+ @machines.initialize_states(@object)
59
+
60
+ assert_equal 'parked', @object.state
61
+ assert_equal 'active', @object.alarm_state
62
+ end
63
+
64
+ def test_should_skip_static_states_if_disabled
65
+ @machines.initialize_states(@object, :static => false)
66
+ assert_nil @object.state
67
+ assert_equal 'active', @object.alarm_state
68
+ end
69
+
70
+ def test_should_not_initialize_existing_static_states_by_default
71
+ @object.state = 'idling'
72
+ @machines.initialize_states(@object)
73
+ assert_equal 'idling', @object.state
74
+ end
75
+
76
+ def test_should_initialize_existing_static_states_if_forced
77
+ @object.state = 'idling'
78
+ @machines.initialize_states(@object, :static => :force)
79
+ assert_equal 'parked', @object.state
80
+ end
81
+
82
+ def test_should_not_initialize_existing_static_states_if_not_forced
83
+ @object.state = 'idling'
84
+ @machines.initialize_states(@object, :static => true)
85
+ assert_equal 'idling', @object.state
86
+ end
87
+
88
+ def test_should_skip_dynamic_states_if_disabled
89
+ @machines.initialize_states(@object, :dynamic => false)
90
+ assert_equal 'parked', @object.state
91
+ assert_nil @object.alarm_state
92
+ end
93
+
94
+ def test_should_not_initialize_existing_dynamic_states_by_default
95
+ @object.alarm_state = 'inactive'
96
+ @machines.initialize_states(@object)
97
+ assert_equal 'inactive', @object.alarm_state
98
+ end
99
+
100
+ def test_should_initialize_existing_dynamic_states_if_forced
101
+ @object.alarm_state = 'inactive'
102
+ @machines.initialize_states(@object, :dynamic => :force)
103
+ assert_equal 'active', @object.alarm_state
104
+ end
105
+
106
+ def test_should_not_initialize_existing_dynamic_states_if_not_forced
107
+ @object.alarm_state = 'inactive'
108
+ @machines.initialize_states(@object, :dynamic => true)
109
+ assert_equal 'inactive', @object.alarm_state
110
+ end
111
+ end
112
+
113
+ class MachineCollectionFireTest < Test::Unit::TestCase
114
+ def setup
115
+ @machines = EnumStateMachine::MachineCollection.new
116
+
117
+ @klass = Class.new do
118
+ attr_reader :saved
119
+
120
+ def save
121
+ @saved = true
122
+ end
123
+ end
124
+
125
+ # First machine
126
+ @machines[:state] = @state = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
127
+ @state.event :ignite do
128
+ transition :parked => :idling
129
+ end
130
+ @state.event :park do
131
+ transition :idling => :parked
132
+ end
133
+
134
+ # Second machine
135
+ @machines[:alarm_state] = @alarm_state = EnumStateMachine::Machine.new(@klass, :alarm_state, :initial => :active, :action => :save, :namespace => 'alarm')
136
+ @alarm_state.event :enable do
137
+ transition :off => :active
138
+ end
139
+ @alarm_state.event :disable do
140
+ transition :active => :off
141
+ end
142
+
143
+ @object = @klass.new
144
+ end
145
+
146
+ def test_should_raise_exception_if_invalid_event_specified
147
+ exception = assert_raise(EnumStateMachine::InvalidEvent) { @machines.fire_events(@object, :invalid) }
148
+ assert_equal :invalid, exception.event
149
+
150
+ exception = assert_raise(EnumStateMachine::InvalidEvent) { @machines.fire_events(@object, :ignite, :invalid) }
151
+ assert_equal :invalid, exception.event
152
+ end
153
+
154
+ def test_should_fail_if_any_event_cannot_transition
155
+ assert !@machines.fire_events(@object, :park, :disable_alarm)
156
+ assert_equal 'parked', @object.state
157
+ assert_equal 'active', @object.alarm_state
158
+ assert !@object.saved
159
+
160
+ assert !@machines.fire_events(@object, :ignite, :enable_alarm)
161
+ assert_equal 'parked', @object.state
162
+ assert_equal 'active', @object.alarm_state
163
+ assert !@object.saved
164
+ end
165
+
166
+ def test_should_run_failure_callbacks_if_any_event_cannot_transition
167
+ @state_failure_run = @alarm_state_failure_run = false
168
+
169
+ @machines[:state].after_failure {@state_failure_run = true}
170
+ @machines[:alarm_state].after_failure {@alarm_state_failure_run = true}
171
+
172
+ assert !@machines.fire_events(@object, :park, :disable_alarm)
173
+ assert @state_failure_run
174
+ assert !@alarm_state_failure_run
175
+ end
176
+
177
+ def test_should_be_successful_if_all_events_transition
178
+ assert @machines.fire_events(@object, :ignite, :disable_alarm)
179
+ assert_equal 'idling', @object.state
180
+ assert_equal 'off', @object.alarm_state
181
+ assert @object.saved
182
+ end
183
+
184
+ def test_should_not_save_if_skipping_action
185
+ assert @machines.fire_events(@object, :ignite, :disable_alarm, false)
186
+ assert_equal 'idling', @object.state
187
+ assert_equal 'off', @object.alarm_state
188
+ assert !@object.saved
189
+ end
190
+ end
191
+
192
+ class MachineCollectionFireWithTransactionsTest < Test::Unit::TestCase
193
+ def setup
194
+ @machines = EnumStateMachine::MachineCollection.new
195
+
196
+ @klass = Class.new do
197
+ attr_accessor :allow_save
198
+
199
+ def save
200
+ @allow_save
201
+ end
202
+ end
203
+
204
+ EnumStateMachine::Integrations.const_set('Custom', Module.new do
205
+ include EnumStateMachine::Integrations::Base
206
+
207
+ attr_reader :rolled_back
208
+
209
+ def transaction(object)
210
+ @rolled_back = yield
211
+ end
212
+ end)
213
+
214
+ # First machine
215
+ @machines[:state] = @state = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save, :integration => :custom)
216
+ @state.event :ignite do
217
+ transition :parked => :idling
218
+ end
219
+
220
+ # Second machine
221
+ @machines[:alarm_state] = @alarm_state = EnumStateMachine::Machine.new(@klass, :alarm_state, :initial => :active, :action => :save, :namespace => 'alarm', :integration => :custom)
222
+ @alarm_state.event :disable do
223
+ transition :active => :off
224
+ end
225
+
226
+ @object = @klass.new
227
+ end
228
+
229
+ def test_should_not_rollback_if_successful
230
+ @object.allow_save = true
231
+
232
+ assert @machines.fire_events(@object, :ignite, :disable_alarm)
233
+ assert_equal true, @state.rolled_back
234
+ assert_nil @alarm_state.rolled_back
235
+ assert_equal 'idling', @object.state
236
+ assert_equal 'off', @object.alarm_state
237
+ end
238
+
239
+ def test_should_rollback_if_not_successful
240
+ @object.allow_save = false
241
+
242
+ assert !@machines.fire_events(@object, :ignite, :disable_alarm)
243
+ assert_equal false, @state.rolled_back
244
+ assert_nil @alarm_state.rolled_back
245
+ assert_equal 'parked', @object.state
246
+ assert_equal 'active', @object.alarm_state
247
+ end
248
+
249
+ def test_should_run_failure_callbacks_if_not_successful
250
+ @object.allow_save = false
251
+ @state_failure_run = @alarm_state_failure_run = false
252
+
253
+ @machines[:state].after_failure {@state_failure_run = true}
254
+ @machines[:alarm_state].after_failure {@alarm_state_failure_run = true}
255
+
256
+ assert !@machines.fire_events(@object, :ignite, :disable_alarm)
257
+ assert @state_failure_run
258
+ assert @alarm_state_failure_run
259
+ end
260
+
261
+ def teardown
262
+ EnumStateMachine::Integrations.send(:remove_const, 'Custom')
263
+ end
264
+ end
265
+
266
+ class MachineCollectionFireWithValidationsTest < Test::Unit::TestCase
267
+ def setup
268
+ EnumStateMachine::Integrations.const_set('Custom', Module.new do
269
+ include EnumStateMachine::Integrations::Base
270
+
271
+ def invalidate(object, attribute, message, values = [])
272
+ (object.errors ||= []) << generate_message(message, values)
273
+ end
274
+
275
+ def reset(object)
276
+ object.errors = []
277
+ end
278
+ end)
279
+
280
+ @klass = Class.new do
281
+ attr_accessor :errors
282
+
283
+ def initialize
284
+ @errors = []
285
+ super
286
+ end
287
+ end
288
+
289
+ @machines = EnumStateMachine::MachineCollection.new
290
+ @machines[:state] = @state = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :integration => :custom)
291
+ @state.event :ignite do
292
+ transition :parked => :idling
293
+ end
294
+
295
+ @machines[:alarm_state] = @alarm_state = EnumStateMachine::Machine.new(@klass, :alarm_state, :initial => :active, :namespace => 'alarm', :integration => :custom)
296
+ @alarm_state.event :disable do
297
+ transition :active => :off
298
+ end
299
+
300
+ @object = @klass.new
301
+ end
302
+
303
+ def test_should_not_invalidate_if_transitions_exist
304
+ assert @machines.fire_events(@object, :ignite, :disable_alarm)
305
+ assert_equal [], @object.errors
306
+ end
307
+
308
+ def test_should_invalidate_if_no_transitions_exist
309
+ @object.state = 'idling'
310
+ @object.alarm_state = 'off'
311
+
312
+ assert !@machines.fire_events(@object, :ignite, :disable_alarm)
313
+ assert_equal ['cannot transition via "ignite"', 'cannot transition via "disable"'], @object.errors
314
+ end
315
+
316
+ def test_should_run_failure_callbacks_if_no_transitions_exist
317
+ @object.state = 'idling'
318
+ @object.alarm_state = 'off'
319
+ @state_failure_run = @alarm_state_failure_run = false
320
+
321
+ @machines[:state].after_failure {@state_failure_run = true}
322
+ @machines[:alarm_state].after_failure {@alarm_state_failure_run = true}
323
+
324
+ assert !@machines.fire_events(@object, :ignite, :disable_alarm)
325
+ assert @state_failure_run
326
+ assert @alarm_state_failure_run
327
+ end
328
+
329
+ def teardown
330
+ EnumStateMachine::Integrations.send(:remove_const, 'Custom')
331
+ end
332
+ end
333
+
334
+ class MachineCollectionTransitionsWithoutEventsTest < Test::Unit::TestCase
335
+ def setup
336
+ @klass = Class.new
337
+
338
+ @machines = EnumStateMachine::MachineCollection.new
339
+ @machines[:state] = @machine = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
340
+ @machine.event :ignite do
341
+ transition :parked => :idling
342
+ end
343
+
344
+ @object = @klass.new
345
+ @object.state_event = nil
346
+ @transitions = @machines.transitions(@object, :save)
347
+ end
348
+
349
+ def test_should_be_empty
350
+ assert @transitions.empty?
351
+ end
352
+
353
+ def test_should_perform
354
+ assert_equal true, @transitions.perform
355
+ end
356
+ end
357
+
358
+ class MachineCollectionTransitionsWithBlankEventsTest < Test::Unit::TestCase
359
+ def setup
360
+ @klass = Class.new
361
+
362
+ @machines = EnumStateMachine::MachineCollection.new
363
+ @machines[:state] = @machine = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
364
+ @machine.event :ignite do
365
+ transition :parked => :idling
366
+ end
367
+
368
+ @object = @klass.new
369
+ @object.state_event = ''
370
+ @transitions = @machines.transitions(@object, :save)
371
+ end
372
+
373
+ def test_should_be_empty
374
+ assert @transitions.empty?
375
+ end
376
+
377
+ def test_should_perform
378
+ assert_equal true, @transitions.perform
379
+ end
380
+ end
381
+
382
+ class MachineCollectionTransitionsWithInvalidEventsTest < Test::Unit::TestCase
383
+ def setup
384
+ @klass = Class.new
385
+
386
+ @machines = EnumStateMachine::MachineCollection.new
387
+ @machines[:state] = @machine = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
388
+ @machine.event :ignite do
389
+ transition :parked => :idling
390
+ end
391
+
392
+ @object = @klass.new
393
+ @object.state_event = 'invalid'
394
+ @transitions = @machines.transitions(@object, :save)
395
+ end
396
+
397
+ def test_should_be_empty
398
+ assert @transitions.empty?
399
+ end
400
+
401
+ def test_should_not_perform
402
+ assert_equal false, @transitions.perform
403
+ end
404
+ end
405
+
406
+ class MachineCollectionTransitionsWithoutTransitionTest < Test::Unit::TestCase
407
+ def setup
408
+ @klass = Class.new
409
+
410
+ @machines = EnumStateMachine::MachineCollection.new
411
+ @machines[:state] = @machine = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
412
+ @machine.event :ignite do
413
+ transition :parked => :idling
414
+ end
415
+
416
+ @object = @klass.new
417
+ @object.state = 'idling'
418
+ @object.state_event = 'ignite'
419
+ @transitions = @machines.transitions(@object, :save)
420
+ end
421
+
422
+ def test_should_be_empty
423
+ assert @transitions.empty?
424
+ end
425
+
426
+ def test_should_not_perform
427
+ assert_equal false, @transitions.perform
428
+ end
429
+ end
430
+
431
+ class MachineCollectionTransitionsWithTransitionTest < Test::Unit::TestCase
432
+ def setup
433
+ @klass = Class.new
434
+
435
+ @machines = EnumStateMachine::MachineCollection.new
436
+ @machines[:state] = @machine = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
437
+ @machine.event :ignite do
438
+ transition :parked => :idling
439
+ end
440
+
441
+ @object = @klass.new
442
+ @object.state_event = 'ignite'
443
+ @transitions = @machines.transitions(@object, :save)
444
+ end
445
+
446
+ def test_should_not_be_empty
447
+ assert_equal 1, @transitions.length
448
+ end
449
+
450
+ def test_should_perform
451
+ assert_equal true, @transitions.perform
452
+ end
453
+ end
454
+
455
+ class MachineCollectionTransitionsWithSameActionsTest < Test::Unit::TestCase
456
+ def setup
457
+ @klass = Class.new
458
+
459
+ @machines = EnumStateMachine::MachineCollection.new
460
+ @machines[:state] = @machine = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
461
+ @machine.event :ignite do
462
+ transition :parked => :idling
463
+ end
464
+ @machines[:status] = @machine = EnumStateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :save)
465
+ @machine.event :shift_up do
466
+ transition :first_gear => :second_gear
467
+ end
468
+
469
+ @object = @klass.new
470
+ @object.state_event = 'ignite'
471
+ @object.status_event = 'shift_up'
472
+ @transitions = @machines.transitions(@object, :save)
473
+ end
474
+
475
+ def test_should_not_be_empty
476
+ assert_equal 2, @transitions.length
477
+ end
478
+
479
+ def test_should_perform
480
+ assert_equal true, @transitions.perform
481
+ end
482
+ end
483
+
484
+ class MachineCollectionTransitionsWithDifferentActionsTest < Test::Unit::TestCase
485
+ def setup
486
+ @klass = Class.new
487
+
488
+ @machines = EnumStateMachine::MachineCollection.new
489
+ @machines[:state] = @state = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
490
+ @state.event :ignite do
491
+ transition :parked => :idling
492
+ end
493
+ @machines[:status] = @status = EnumStateMachine::Machine.new(@klass, :status, :initial => :first_gear, :action => :persist)
494
+ @status.event :shift_up do
495
+ transition :first_gear => :second_gear
496
+ end
497
+
498
+ @object = @klass.new
499
+ @object.state_event = 'ignite'
500
+ @object.status_event = 'shift_up'
501
+ @transitions = @machines.transitions(@object, :save)
502
+ end
503
+
504
+ def test_should_only_select_matching_actions
505
+ assert_equal 1, @transitions.length
506
+ end
507
+ end
508
+
509
+ class MachineCollectionTransitionsWithExisitingTransitionsTest < Test::Unit::TestCase
510
+ def setup
511
+ @klass = Class.new
512
+
513
+ @machines = EnumStateMachine::MachineCollection.new
514
+ @machines[:state] = @machine = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
515
+ @machine.event :ignite do
516
+ transition :parked => :idling
517
+ end
518
+
519
+ @object = @klass.new
520
+ @object.send(:state_event_transition=, EnumStateMachine::Transition.new(@object, @machine, :ignite, :parked, :idling))
521
+ @transitions = @machines.transitions(@object, :save)
522
+ end
523
+
524
+ def test_should_not_be_empty
525
+ assert_equal 1, @transitions.length
526
+ end
527
+
528
+ def test_should_perform
529
+ assert_equal true, @transitions.perform
530
+ end
531
+ end
532
+
533
+ class MachineCollectionTransitionsWithCustomOptionsTest < Test::Unit::TestCase
534
+ def setup
535
+ @klass = Class.new
536
+
537
+ @machines = EnumStateMachine::MachineCollection.new
538
+ @machines[:state] = @machine = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
539
+ @machine.event :ignite do
540
+ transition :parked => :idling
541
+ end
542
+
543
+ @object = @klass.new
544
+ @transitions = @machines.transitions(@object, :save, :after => false)
545
+ end
546
+
547
+ def test_should_use_custom_options
548
+ assert @transitions.skip_after
549
+ end
550
+ end
551
+
552
+ class MachineCollectionFireAttributesWithValidationsTest < Test::Unit::TestCase
553
+ def setup
554
+ @klass = Class.new do
555
+ attr_accessor :errors
556
+
557
+ def initialize
558
+ @errors = []
559
+ super
560
+ end
561
+ end
562
+
563
+ @machines = EnumStateMachine::MachineCollection.new
564
+ @machines[:state] = @machine = EnumStateMachine::Machine.new(@klass, :state, :initial => :parked, :action => :save)
565
+ @machine.event :ignite do
566
+ transition :parked => :idling
567
+ end
568
+
569
+ class << @machine
570
+ def invalidate(object, attribute, message, values = [])
571
+ (object.errors ||= []) << generate_message(message, values)
572
+ end
573
+
574
+ def reset(object)
575
+ object.errors = []
576
+ end
577
+ end
578
+
579
+ @object = @klass.new
580
+ end
581
+
582
+ def test_should_invalidate_if_event_is_invalid
583
+ @object.state_event = 'invalid'
584
+ @machines.transitions(@object, :save)
585
+
586
+ assert !@object.errors.empty?
587
+ end
588
+
589
+ def test_should_invalidate_if_no_transition_exists
590
+ @object.state = 'idling'
591
+ @object.state_event = 'ignite'
592
+ @machines.transitions(@object, :save)
593
+
594
+ assert !@object.errors.empty?
595
+ end
596
+
597
+ def test_should_not_invalidate_if_transition_exists
598
+ @object.state_event = 'ignite'
599
+ @machines.transitions(@object, :save)
600
+
601
+ assert @object.errors.empty?
602
+ end
603
+ end