state_machines 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.idea/.name +1 -0
  4. data/.idea/.rakeTasks +7 -0
  5. data/.idea/cssxfire.xml +9 -0
  6. data/.idea/encodings.xml +5 -0
  7. data/.idea/misc.xml +5 -0
  8. data/.idea/modules.xml +12 -0
  9. data/.idea/scopes/scope_settings.xml +5 -0
  10. data/.idea/state_machine2.iml +34 -0
  11. data/.idea/vcs.xml +9 -0
  12. data/.idea/workspace.xml +1156 -0
  13. data/.rspec +3 -0
  14. data/.travis.yml +8 -0
  15. data/Gemfile +4 -0
  16. data/LICENSE.txt +23 -0
  17. data/README.md +29 -0
  18. data/Rakefile +1 -0
  19. data/lib/state_machines/assertions.rb +40 -0
  20. data/lib/state_machines/branch.rb +187 -0
  21. data/lib/state_machines/callback.rb +220 -0
  22. data/lib/state_machines/core.rb +25 -0
  23. data/lib/state_machines/core_ext/class/state_machine.rb +5 -0
  24. data/lib/state_machines/core_ext.rb +2 -0
  25. data/lib/state_machines/error.rb +13 -0
  26. data/lib/state_machines/eval_helpers.rb +87 -0
  27. data/lib/state_machines/event.rb +246 -0
  28. data/lib/state_machines/event_collection.rb +141 -0
  29. data/lib/state_machines/extensions.rb +148 -0
  30. data/lib/state_machines/helper_module.rb +17 -0
  31. data/lib/state_machines/integrations/base.rb +100 -0
  32. data/lib/state_machines/integrations.rb +113 -0
  33. data/lib/state_machines/machine.rb +2234 -0
  34. data/lib/state_machines/machine_collection.rb +84 -0
  35. data/lib/state_machines/macro_methods.rb +520 -0
  36. data/lib/state_machines/matcher.rb +123 -0
  37. data/lib/state_machines/matcher_helpers.rb +54 -0
  38. data/lib/state_machines/node_collection.rb +221 -0
  39. data/lib/state_machines/path.rb +120 -0
  40. data/lib/state_machines/path_collection.rb +90 -0
  41. data/lib/state_machines/state.rb +276 -0
  42. data/lib/state_machines/state_collection.rb +112 -0
  43. data/lib/state_machines/state_context.rb +138 -0
  44. data/lib/state_machines/transition.rb +470 -0
  45. data/lib/state_machines/transition_collection.rb +245 -0
  46. data/lib/state_machines/version.rb +3 -0
  47. data/lib/state_machines/yard.rb +8 -0
  48. data/lib/state_machines.rb +3 -0
  49. data/spec/errors/default_spec.rb +14 -0
  50. data/spec/errors/with_message_spec.rb +39 -0
  51. data/spec/helpers/helper_spec.rb +14 -0
  52. data/spec/internal/app/models/auto_shop.rb +31 -0
  53. data/spec/internal/app/models/car.rb +19 -0
  54. data/spec/internal/app/models/model_base.rb +6 -0
  55. data/spec/internal/app/models/motorcycle.rb +9 -0
  56. data/spec/internal/app/models/traffic_light.rb +47 -0
  57. data/spec/internal/app/models/vehicle.rb +123 -0
  58. data/spec/machine_spec.rb +3167 -0
  59. data/spec/matcher_helpers_spec.rb +39 -0
  60. data/spec/matcher_spec.rb +157 -0
  61. data/spec/models/auto_shop_spec.rb +41 -0
  62. data/spec/models/car_spec.rb +90 -0
  63. data/spec/models/motorcycle_spec.rb +44 -0
  64. data/spec/models/traffic_light_spec.rb +56 -0
  65. data/spec/models/vehicle_spec.rb +580 -0
  66. data/spec/node_collection_spec.rb +371 -0
  67. data/spec/path_collection_spec.rb +271 -0
  68. data/spec/path_spec.rb +488 -0
  69. data/spec/spec_helper.rb +6 -0
  70. data/spec/state_collection_spec.rb +352 -0
  71. data/spec/state_context_spec.rb +442 -0
  72. data/spec/state_machine_spec.rb +29 -0
  73. data/spec/state_spec.rb +970 -0
  74. data/spec/support/migration_helpers.rb +50 -0
  75. data/spec/support/models.rb +6 -0
  76. data/spec/transition_collection_spec.rb +2199 -0
  77. data/spec/transition_spec.rb +1558 -0
  78. data/state_machines.gemspec +23 -0
  79. metadata +194 -0
@@ -0,0 +1,371 @@
1
+ require 'spec_helper'
2
+
3
+ class Node < Struct.new(:name, :value, :machine)
4
+ def context
5
+ yield
6
+ end
7
+ end
8
+ describe StateMachines::NodeCollection do
9
+ context 'ByDefault' do
10
+ before(:each) do
11
+ @machine = StateMachines::Machine.new(Class.new)
12
+ @collection = StateMachines::NodeCollection.new(@machine)
13
+ end
14
+
15
+ it 'should_not_have_any_nodes' do
16
+ assert_equal 0, @collection.length
17
+ end
18
+
19
+ it 'should_have_a_machine' do
20
+ assert_equal @machine, @collection.machine
21
+ end
22
+
23
+ it 'should_index_by_name' do
24
+ @collection << object = Node.new(:parked)
25
+ assert_equal object, @collection[:parked]
26
+ end
27
+ end
28
+
29
+ context '' do
30
+ before(:each) do
31
+ @machine = StateMachines::Machine.new(Class.new)
32
+ @collection = StateMachines::NodeCollection.new(@machine)
33
+ end
34
+
35
+ it 'should_raise_exception_if_invalid_option_specified' do
36
+ assert_raise(ArgumentError) { StateMachines::NodeCollection.new(@machine, :invalid => true) }
37
+ # FIXME
38
+ #assert_equal 'Invalid key(s): invalid', exception.message
39
+ end
40
+
41
+ it 'should_raise_exception_on_lookup_if_invalid_index_specified' do
42
+ assert_raise(ArgumentError) { @collection[:something, :invalid] }
43
+ # FIXME
44
+ #assert_equal 'Invalid index: :invalid', exception.message
45
+ end
46
+
47
+ it 'should_raise_exception_on_fetch_if_invalid_index_specified' do
48
+ assert_raise(ArgumentError) { @collection.fetch(:something, :invalid) }
49
+ # FIXME
50
+ #assert_equal 'Invalid index: :invalid', exception.message
51
+ end
52
+ end
53
+
54
+ context 'AfterBeingCopied' do
55
+ before(:each) do
56
+ machine = StateMachines::Machine.new(Class.new)
57
+ @collection = StateMachines::NodeCollection.new(machine)
58
+ @collection << @parked = Node.new(:parked)
59
+
60
+ @contexts_run = contexts_run = []
61
+ @collection.context([:parked]) { contexts_run << :parked }
62
+ @contexts_run.clear
63
+
64
+ @copied_collection = @collection.dup
65
+ @copied_collection << @idling = Node.new(:idling)
66
+ @copied_collection.context([:first_gear]) { contexts_run << :first_gear }
67
+ end
68
+
69
+ it 'should_not_modify_the_original_list' do
70
+ assert_equal 1, @collection.length
71
+ assert_equal 2, @copied_collection.length
72
+ end
73
+
74
+ it 'should_not_modify_the_indices' do
75
+ assert_nil @collection[:idling]
76
+ assert_equal @idling, @copied_collection[:idling]
77
+ end
78
+
79
+ it 'should_copy_each_node' do
80
+ assert_not_same @parked, @copied_collection[:parked]
81
+ end
82
+
83
+ it 'should_not_run_contexts' do
84
+ assert_equal [], @contexts_run
85
+ end
86
+
87
+ it 'should_not_modify_contexts' do
88
+ @collection << Node.new(:first_gear)
89
+ assert_equal [], @contexts_run
90
+ end
91
+
92
+ it 'should_copy_contexts' do
93
+ @copied_collection << Node.new(:parked)
94
+ assert !@contexts_run.empty?
95
+ end
96
+ end
97
+
98
+ context 'WithoutIndices' do
99
+ before(:each) do
100
+ machine = StateMachines::Machine.new(Class.new)
101
+ @collection = StateMachines::NodeCollection.new(machine, :index => {})
102
+ end
103
+
104
+ it 'should_allow_adding_node' do
105
+ @collection << Object.new
106
+ assert_equal 1, @collection.length
107
+ end
108
+
109
+ it 'should_not_allow_keys_retrieval' do
110
+ assert_raise(ArgumentError) { @collection.keys }
111
+ # FIXME
112
+ #assert_equal 'No indices configured', exception.message
113
+ end
114
+
115
+ it 'should_not_allow_lookup' do
116
+ @collection << Object.new
117
+ assert_raise(ArgumentError) { @collection[0] }
118
+ # FIXME
119
+ # assert_equal 'No indices configured', exception.message
120
+ end
121
+
122
+ it 'should_not_allow_fetching' do
123
+ @collection << Object.new
124
+ assert_raise(ArgumentError) { @collection.fetch(0) }
125
+ # FIXME
126
+ #assert_equal 'No indices configured', exception.message
127
+ end
128
+ end
129
+
130
+ context 'WithIndices' do
131
+ before(:each) do
132
+ machine = StateMachines::Machine.new(Class.new)
133
+ @collection = StateMachines::NodeCollection.new(machine, :index => [:name, :value])
134
+
135
+ @object = Node.new(:parked, 1)
136
+ @collection << @object
137
+ end
138
+
139
+ it 'should_use_first_index_by_default_on_key_retrieval' do
140
+ assert_equal [:parked], @collection.keys
141
+ end
142
+
143
+ it 'should_allow_customizing_index_for_key_retrieval' do
144
+ assert_equal [1], @collection.keys(:value)
145
+ end
146
+
147
+ it 'should_use_first_index_by_default_on_lookup' do
148
+ assert_equal @object, @collection[:parked]
149
+ assert_nil @collection[1]
150
+ end
151
+
152
+ it 'should_allow_customizing_index_on_lookup' do
153
+ assert_equal @object, @collection[1, :value]
154
+ assert_nil @collection[:parked, :value]
155
+ end
156
+
157
+ it 'should_use_first_index_by_default_on_fetch' do
158
+ assert_equal @object, @collection.fetch(:parked)
159
+ assert_raise(IndexError) { @collection.fetch(1) }
160
+ # FIXME
161
+ #assert_equal '1 is an invalid name', exception.message
162
+ end
163
+
164
+ it 'should_allow_customizing_index_on_fetch' do
165
+ assert_equal @object, @collection.fetch(1, :value)
166
+ assert_raise(IndexError) { @collection.fetch(:parked, :value) }
167
+ # FIXME
168
+ #assert_equal ':parked is an invalid value', exception.message
169
+ end
170
+ end
171
+
172
+ context 'WithNodes' do
173
+ before(:each) do
174
+ @machine = StateMachines::Machine.new(Class.new)
175
+ @collection = StateMachines::NodeCollection.new(@machine)
176
+
177
+ @parked = Node.new(:parked, nil, @machine)
178
+ @idling = Node.new(:idling, nil, @machine)
179
+
180
+ @collection << @parked
181
+ @collection << @idling
182
+ end
183
+
184
+ it 'should_be_able_to_enumerate' do
185
+ order = []
186
+ @collection.each { |object| order << object }
187
+
188
+ assert_equal [@parked, @idling], order
189
+ end
190
+
191
+ it 'should_be_able_to_concatenate_multiple_nodes' do
192
+ @first_gear = Node.new(:first_gear, nil, @machine)
193
+ @second_gear = Node.new(:second_gear, nil, @machine)
194
+ @collection.concat([@first_gear, @second_gear])
195
+
196
+ order = []
197
+ @collection.each { |object| order << object }
198
+ assert_equal [@parked, @idling, @first_gear, @second_gear], order
199
+ end
200
+
201
+ it 'should_be_able_to_access_by_index' do
202
+ assert_equal @parked, @collection.at(0)
203
+ assert_equal @idling, @collection.at(1)
204
+ end
205
+
206
+ it 'should_deep_copy_machine_changes' do
207
+ new_machine = StateMachines::Machine.new(Class.new)
208
+ @collection.machine = new_machine
209
+
210
+ assert_equal new_machine, @collection.machine
211
+ assert_equal new_machine, @parked.machine
212
+ assert_equal new_machine, @idling.machine
213
+ end
214
+ end
215
+
216
+ context 'AfterUpdate' do
217
+ before(:each) do
218
+ machine = StateMachines::Machine.new(Class.new)
219
+ @collection = StateMachines::NodeCollection.new(machine, :index => [:name, :value])
220
+
221
+ @parked = Node.new(:parked, 1)
222
+ @idling = Node.new(:idling, 2)
223
+
224
+ @collection << @parked << @idling
225
+
226
+ @parked.name = :parking
227
+ @parked.value = 0
228
+ @collection.update(@parked)
229
+ end
230
+
231
+ it 'should_not_change_the_index' do
232
+ assert_equal @parked, @collection.at(0)
233
+ end
234
+
235
+ it 'should_not_duplicate_in_the_collection' do
236
+ assert_equal 2, @collection.length
237
+ end
238
+
239
+ it 'should_add_each_indexed_key' do
240
+ assert_equal @parked, @collection[:parking]
241
+ assert_equal @parked, @collection[0, :value]
242
+ end
243
+
244
+ it 'should_remove_each_old_indexed_key' do
245
+ assert_nil @collection[:parked]
246
+ assert_nil @collection[1, :value]
247
+ end
248
+ end
249
+
250
+ context 'WithStringIndex' do
251
+ before(:each) do
252
+ machine = StateMachines::Machine.new(Class.new)
253
+ @collection = StateMachines::NodeCollection.new(machine, :index => [:name, :value])
254
+
255
+ @parked = Node.new(:parked, 1)
256
+ @collection << @parked
257
+ end
258
+
259
+ it 'should_index_by_name' do
260
+ assert_equal @parked, @collection[:parked]
261
+ end
262
+
263
+ it 'should_index_by_string_name' do
264
+ assert_equal @parked, @collection['parked']
265
+ end
266
+ end
267
+
268
+ context 'WithSymbolIndex' do
269
+ before(:each) do
270
+ machine = StateMachines::Machine.new(Class.new)
271
+ @collection = StateMachines::NodeCollection.new(machine, :index => [:name, :value])
272
+
273
+ @parked = Node.new('parked', 1)
274
+ @collection << @parked
275
+ end
276
+
277
+ it 'should_index_by_name' do
278
+ assert_equal @parked, @collection['parked']
279
+ end
280
+
281
+ it 'should_index_by_symbol_name' do
282
+ assert_equal @parked, @collection[:parked]
283
+ end
284
+ end
285
+
286
+ context 'WithNumericIndex' do
287
+ before(:each) do
288
+ machine = StateMachines::Machine.new(Class.new)
289
+ @collection = StateMachines::NodeCollection.new(machine, :index => [:name, :value])
290
+
291
+ @parked = Node.new(10, 1)
292
+ @collection << @parked
293
+ end
294
+
295
+ it 'should_index_by_name' do
296
+ assert_equal @parked, @collection[10]
297
+ end
298
+
299
+ it 'should_index_by_string_name' do
300
+ assert_equal @parked, @collection['10']
301
+ end
302
+
303
+ it 'should_index_by_symbol_name' do
304
+ assert_equal @parked, @collection[:'10']
305
+ end
306
+ end
307
+
308
+ context 'WithPredefinedContexts' do
309
+ before(:each) do
310
+ machine = StateMachines::Machine.new(Class.new)
311
+ @collection = StateMachines::NodeCollection.new(machine)
312
+
313
+ @contexts_run = contexts_run = []
314
+ @collection.context([:parked]) { contexts_run << :parked }
315
+ @collection.context([:parked]) { contexts_run << :second_parked }
316
+ end
317
+
318
+ it 'should_run_contexts_in_the_order_defined' do
319
+ @collection << Node.new(:parked)
320
+ assert_equal [:parked, :second_parked], @contexts_run
321
+ end
322
+
323
+ it 'should_not_run_contexts_if_not_matched' do
324
+ @collection << Node.new(:idling)
325
+ assert_equal [], @contexts_run
326
+ end
327
+ end
328
+
329
+ context 'WithPostdefinedContexts' do
330
+ before(:each) do
331
+ machine = StateMachines::Machine.new(Class.new)
332
+ @collection = StateMachines::NodeCollection.new(machine)
333
+ @collection << Node.new(:parked)
334
+ end
335
+
336
+ it 'should_run_context_if_matched' do
337
+ contexts_run = []
338
+ @collection.context([:parked]) { contexts_run << :parked }
339
+ assert_equal [:parked], contexts_run
340
+ end
341
+
342
+ it 'should_not_run_contexts_if_not_matched' do
343
+ contexts_run = []
344
+ @collection.context([:idling]) { contexts_run << :idling }
345
+ assert_equal [], contexts_run
346
+ end
347
+ end
348
+
349
+ context 'WithMatcherContexts' do
350
+ before(:each) do
351
+ machine = StateMachines::Machine.new(Class.new)
352
+ @collection = StateMachines::NodeCollection.new(machine)
353
+ @collection << Node.new(:parked)
354
+ end
355
+
356
+ it 'should_always_run_all_matcher_context' do
357
+ contexts_run = []
358
+ @collection.context([StateMachines::AllMatcher.instance]) { contexts_run << :all }
359
+ assert_equal [:all], contexts_run
360
+ end
361
+
362
+ it 'should_only_run_blacklist_matcher_if_not_matched' do
363
+ contexts_run = []
364
+ @collection.context([StateMachines::BlacklistMatcher.new([:parked])]) { contexts_run << :blacklist }
365
+ assert_equal [], contexts_run
366
+
367
+ @collection << Node.new(:idling)
368
+ assert_equal [:blacklist], contexts_run
369
+ end
370
+ end
371
+ end
@@ -0,0 +1,271 @@
1
+ require 'spec_helper'
2
+
3
+ describe StateMachines::PathCollection do
4
+ context 'ByDefault' do
5
+ before(:each) do
6
+ @klass = Class.new
7
+ @machine = StateMachines::Machine.new(@klass)
8
+ @machine.state :parked
9
+
10
+ @object = @klass.new
11
+ @object.state = 'parked'
12
+
13
+ @paths = StateMachines::PathCollection.new(@object, @machine)
14
+ end
15
+
16
+ it 'should_have_an_object' do
17
+ assert_equal @object, @paths.object
18
+ end
19
+
20
+ it 'should_have_a_machine' do
21
+ assert_equal @machine, @paths.machine
22
+ end
23
+
24
+ it 'should_have_a_from_name' do
25
+ assert_equal :parked, @paths.from_name
26
+ end
27
+
28
+ it 'should_not_have_a_to_name' do
29
+ assert_nil @paths.to_name
30
+ end
31
+
32
+ it 'should_have_no_from_states' do
33
+ assert_equal [], @paths.from_states
34
+ end
35
+
36
+ it 'should_have_no_to_states' do
37
+ assert_equal [], @paths.to_states
38
+ end
39
+
40
+ it 'should_have_no_events' do
41
+ assert_equal [], @paths.events
42
+ end
43
+
44
+ it 'should_have_no_paths' do
45
+ assert @paths.empty?
46
+ end
47
+ end
48
+
49
+ context '' do
50
+ before(:each) do
51
+ @klass = Class.new
52
+ @machine = StateMachines::Machine.new(@klass)
53
+ @object = @klass.new
54
+ end
55
+
56
+ it 'should_raise_exception_if_invalid_option_specified' do
57
+ assert_raise(ArgumentError) { StateMachines::PathCollection.new(@object, @machine, :invalid => true) }
58
+ # FIXME
59
+ # assert_equal 'Invalid key(s): invalid', exception.message
60
+ end
61
+
62
+ it 'should_raise_exception_if_invalid_from_state_specified' do
63
+ assert_raise(IndexError) { StateMachines::PathCollection.new(@object, @machine, :from => :invalid) }
64
+ # FIXME
65
+ #assert_equal ':invalid is an invalid name', exception.message
66
+ end
67
+
68
+ it 'should_raise_exception_if_invalid_to_state_specified' do
69
+ assert_raise(IndexError) { StateMachines::PathCollection.new(@object, @machine, :to => :invalid) }
70
+ # FIXME
71
+ #assert_equal ':invalid is an invalid name', exception.message
72
+ end
73
+ end
74
+
75
+ context 'WithPaths' do
76
+ before(:each) do
77
+ @klass = Class.new
78
+ @machine = StateMachines::Machine.new(@klass)
79
+ @machine.state :parked, :idling, :first_gear
80
+ @machine.event :ignite do
81
+ transition :parked => :idling
82
+ end
83
+ @machine.event :shift_up do
84
+ transition :idling => :first_gear
85
+ end
86
+
87
+ @object = @klass.new
88
+ @object.state = 'parked'
89
+
90
+ @paths = StateMachines::PathCollection.new(@object, @machine)
91
+ end
92
+
93
+ it 'should_enumerate_paths' do
94
+ assert_equal [[
95
+ StateMachines::Transition.new(@object, @machine, :ignite, :parked, :idling),
96
+ StateMachines::Transition.new(@object, @machine, :shift_up, :idling, :first_gear)
97
+ ]], @paths
98
+ end
99
+
100
+ it 'should_have_a_from_name' do
101
+ assert_equal :parked, @paths.from_name
102
+ end
103
+
104
+ it 'should_not_have_a_to_name' do
105
+ assert_nil @paths.to_name
106
+ end
107
+
108
+ it 'should_have_from_states' do
109
+ assert_equal [:parked, :idling], @paths.from_states
110
+ end
111
+
112
+ it 'should_have_to_states' do
113
+ assert_equal [:idling, :first_gear], @paths.to_states
114
+ end
115
+
116
+ it 'should_have_no_events' do
117
+ assert_equal [:ignite, :shift_up], @paths.events
118
+ end
119
+ end
120
+
121
+ context 'WithGuardedPaths' do
122
+ before(:each) do
123
+ @klass = Class.new
124
+ @machine = StateMachines::Machine.new(@klass)
125
+ @machine.state :parked, :idling, :first_gear
126
+ @machine.event :ignite do
127
+ transition :parked => :idling, :if => lambda { false }
128
+ end
129
+
130
+ @object = @klass.new
131
+ @object.state = 'parked'
132
+ end
133
+
134
+ it 'should_not_enumerate_paths_if_guard_enabled' do
135
+ assert_equal [], StateMachines::PathCollection.new(@object, @machine)
136
+ end
137
+
138
+ it 'should_enumerate_paths_if_guard_disabled' do
139
+ paths = StateMachines::PathCollection.new(@object, @machine, :guard => false)
140
+ assert_equal [[
141
+ StateMachines::Transition.new(@object, @machine, :ignite, :parked, :idling)
142
+ ]], paths
143
+ end
144
+ end
145
+
146
+ context 'WithDuplicateNodes' do
147
+ before(:each) do
148
+ @klass = Class.new
149
+ @machine = StateMachines::Machine.new(@klass)
150
+ @machine.state :parked, :idling
151
+ @machine.event :shift_up do
152
+ transition :parked => :idling, :idling => :first_gear
153
+ end
154
+ @machine.event :park do
155
+ transition :first_gear => :idling
156
+ end
157
+ @object = @klass.new
158
+ @object.state = 'parked'
159
+
160
+ @paths = StateMachines::PathCollection.new(@object, @machine)
161
+ end
162
+
163
+ it 'should_not_include_duplicates_in_from_states' do
164
+ assert_equal [:parked, :idling, :first_gear], @paths.from_states
165
+ end
166
+
167
+ it 'should_not_include_duplicates_in_to_states' do
168
+ assert_equal [:idling, :first_gear], @paths.to_states
169
+ end
170
+
171
+ it 'should_not_include_duplicates_in_events' do
172
+ assert_equal [:shift_up, :park], @paths.events
173
+ end
174
+ end
175
+
176
+ context 'WithFromState' do
177
+ before(:each) do
178
+ @klass = Class.new
179
+ @machine = StateMachines::Machine.new(@klass)
180
+ @machine.state :parked, :idling, :first_gear
181
+ @machine.event :park do
182
+ transition :idling => :parked
183
+ end
184
+
185
+ @object = @klass.new
186
+ @object.state = 'parked'
187
+
188
+ @paths = StateMachines::PathCollection.new(@object, @machine, :from => :idling)
189
+ end
190
+
191
+ it 'should_generate_paths_from_custom_from_state' do
192
+ assert_equal [[
193
+ StateMachines::Transition.new(@object, @machine, :park, :idling, :parked)
194
+ ]], @paths
195
+ end
196
+
197
+ it 'should_have_a_from_name' do
198
+ assert_equal :idling, @paths.from_name
199
+ end
200
+ end
201
+
202
+ context 'WithToState' do
203
+ before(:each) do
204
+ @klass = Class.new
205
+ @machine = StateMachines::Machine.new(@klass)
206
+ @machine.state :parked, :idling
207
+ @machine.event :ignite do
208
+ transition :parked => :idling
209
+ end
210
+ @machine.event :shift_up do
211
+ transition :parked => :idling, :idling => :first_gear
212
+ end
213
+ @machine.event :shift_down do
214
+ transition :first_gear => :idling
215
+ end
216
+ @object = @klass.new
217
+ @object.state = 'parked'
218
+
219
+ @paths = StateMachines::PathCollection.new(@object, @machine, :to => :idling)
220
+ end
221
+
222
+ it 'should_stop_paths_once_target_state_reached' do
223
+ assert_equal [
224
+ [StateMachines::Transition.new(@object, @machine, :ignite, :parked, :idling)],
225
+ [StateMachines::Transition.new(@object, @machine, :shift_up, :parked, :idling)]
226
+ ], @paths
227
+ end
228
+ end
229
+
230
+ context 'WithDeepPaths' do
231
+ before(:each) do
232
+ @klass = Class.new
233
+ @machine = StateMachines::Machine.new(@klass)
234
+ @machine.state :parked, :idling
235
+ @machine.event :ignite do
236
+ transition :parked => :idling
237
+ end
238
+ @machine.event :shift_up do
239
+ transition :parked => :idling, :idling => :first_gear
240
+ end
241
+ @machine.event :shift_down do
242
+ transition :first_gear => :idling
243
+ end
244
+ @object = @klass.new
245
+ @object.state = 'parked'
246
+
247
+ @paths = StateMachines::PathCollection.new(@object, @machine, :to => :idling, :deep => true)
248
+ end
249
+
250
+ it 'should_allow_target_to_be_reached_more_than_once_per_path' do
251
+ assert_equal [
252
+ [
253
+ StateMachines::Transition.new(@object, @machine, :ignite, :parked, :idling)
254
+ ],
255
+ [
256
+ StateMachines::Transition.new(@object, @machine, :ignite, :parked, :idling),
257
+ StateMachines::Transition.new(@object, @machine, :shift_up, :idling, :first_gear),
258
+ StateMachines::Transition.new(@object, @machine, :shift_down, :first_gear, :idling)
259
+ ],
260
+ [
261
+ StateMachines::Transition.new(@object, @machine, :shift_up, :parked, :idling)
262
+ ],
263
+ [
264
+ StateMachines::Transition.new(@object, @machine, :shift_up, :parked, :idling),
265
+ StateMachines::Transition.new(@object, @machine, :shift_up, :idling, :first_gear),
266
+ StateMachines::Transition.new(@object, @machine, :shift_down, :first_gear, :idling)
267
+ ]
268
+ ], @paths
269
+ end
270
+ end
271
+ end