state_machines 0.0.1

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 (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