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.
- checksums.yaml +4 -4
- data/.gitignore +0 -12
- data/.ruby-version +1 -1
- data/.ruby-version.orig +5 -0
- data/Gemfile +0 -1
- data/Rakefile +0 -18
- data/enum_state_machine.gemspec +35 -0
- data/enum_state_machine.gemspec.orig +43 -0
- data/lib/enum_state_machine/assertions.rb +36 -0
- data/lib/enum_state_machine/branch.rb +225 -0
- data/lib/enum_state_machine/callback.rb +232 -0
- data/lib/enum_state_machine/core.rb +12 -0
- data/lib/enum_state_machine/core_ext/class/state_machine.rb +5 -0
- data/lib/enum_state_machine/core_ext.rb +2 -0
- data/lib/enum_state_machine/error.rb +13 -0
- data/lib/enum_state_machine/eval_helpers.rb +87 -0
- data/lib/enum_state_machine/event.rb +257 -0
- data/lib/enum_state_machine/event_collection.rb +141 -0
- data/lib/enum_state_machine/extensions.rb +149 -0
- data/lib/enum_state_machine/graph.rb +93 -0
- data/lib/enum_state_machine/helper_module.rb +17 -0
- data/lib/enum_state_machine/initializers/rails.rb +22 -0
- data/lib/enum_state_machine/initializers.rb +4 -0
- data/lib/enum_state_machine/integrations/active_model/locale.rb +11 -0
- data/lib/enum_state_machine/integrations/active_model/observer.rb +33 -0
- data/lib/enum_state_machine/integrations/active_model/observer_update.rb +42 -0
- data/lib/enum_state_machine/integrations/active_model/versions.rb +31 -0
- data/lib/enum_state_machine/integrations/active_model.rb +585 -0
- data/lib/enum_state_machine/integrations/active_record/locale.rb +20 -0
- data/lib/enum_state_machine/integrations/active_record/versions.rb +123 -0
- data/lib/enum_state_machine/integrations/active_record.rb +548 -0
- data/lib/enum_state_machine/integrations/base.rb +100 -0
- data/lib/enum_state_machine/integrations.rb +97 -0
- data/lib/enum_state_machine/machine.rb +2292 -0
- data/lib/enum_state_machine/machine_collection.rb +86 -0
- data/lib/enum_state_machine/macro_methods.rb +518 -0
- data/lib/enum_state_machine/matcher.rb +123 -0
- data/lib/enum_state_machine/matcher_helpers.rb +54 -0
- data/lib/enum_state_machine/node_collection.rb +222 -0
- data/lib/enum_state_machine/path.rb +120 -0
- data/lib/enum_state_machine/path_collection.rb +90 -0
- data/lib/enum_state_machine/state.rb +297 -0
- data/lib/enum_state_machine/state_collection.rb +112 -0
- data/lib/enum_state_machine/state_context.rb +138 -0
- data/lib/enum_state_machine/state_enum.rb +23 -0
- data/lib/enum_state_machine/transition.rb +470 -0
- data/lib/enum_state_machine/transition_collection.rb +245 -0
- data/lib/enum_state_machine/version.rb +3 -0
- data/lib/enum_state_machine/yard/handlers/base.rb +32 -0
- data/lib/enum_state_machine/yard/handlers/event.rb +25 -0
- data/lib/enum_state_machine/yard/handlers/machine.rb +344 -0
- data/lib/enum_state_machine/yard/handlers/state.rb +25 -0
- data/lib/enum_state_machine/yard/handlers/transition.rb +47 -0
- data/lib/enum_state_machine/yard/handlers.rb +12 -0
- data/lib/enum_state_machine/yard/templates/default/class/html/setup.rb +30 -0
- data/lib/enum_state_machine/yard/templates/default/class/html/state_machines.erb +12 -0
- data/lib/enum_state_machine/yard/templates.rb +3 -0
- data/lib/enum_state_machine/yard.rb +8 -0
- data/lib/enum_state_machine.rb +9 -0
- data/lib/tasks/enum_state_machine.rake +1 -0
- data/lib/tasks/enum_state_machine.rb +24 -0
- data/lib/yard-enum_state_machine.rb +2 -0
- data/test/functional/state_machine_test.rb +1066 -0
- data/test/unit/graph_test.rb +9 -5
- data/test/unit/integrations/active_model_test.rb +1245 -0
- data/test/unit/integrations/active_record_test.rb +2551 -0
- data/test/unit/integrations/base_test.rb +104 -0
- data/test/unit/integrations_test.rb +71 -0
- data/test/unit/invalid_event_test.rb +20 -0
- data/test/unit/invalid_parallel_transition_test.rb +18 -0
- data/test/unit/invalid_transition_test.rb +115 -0
- data/test/unit/machine_collection_test.rb +603 -0
- data/test/unit/machine_test.rb +3395 -0
- data/test/unit/state_machine_test.rb +31 -0
- metadata +212 -44
- data/Appraisals +0 -28
- data/gemfiles/active_model_4.0.4.gemfile +0 -9
- data/gemfiles/active_model_4.0.4.gemfile.lock +0 -51
- data/gemfiles/active_record_4.0.4.gemfile +0 -11
- data/gemfiles/active_record_4.0.4.gemfile.lock +0 -61
- data/gemfiles/default.gemfile +0 -7
- data/gemfiles/default.gemfile.lock +0 -27
- data/gemfiles/graphviz_1.0.9.gemfile +0 -7
- 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
|