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,352 @@
1
+ require 'spec_helper'
2
+
3
+ context 'ByDefault' do
4
+ before(:each) do
5
+ @machine = StateMachines::Machine.new(Class.new)
6
+ @states = StateMachines::StateCollection.new(@machine)
7
+ end
8
+
9
+ it 'should_not_have_any_nodes' do
10
+ assert_equal 0, @states.length
11
+ end
12
+
13
+ it 'should_have_a_machine' do
14
+ assert_equal @machine, @states.machine
15
+ end
16
+
17
+ it 'should_be_empty_by_priority' do
18
+ assert_equal [], @states.by_priority
19
+ end
20
+ end
21
+
22
+ context '' do
23
+ before(:each) do
24
+ @klass = Class.new
25
+ @machine = StateMachines::Machine.new(@klass)
26
+ @states = StateMachines::StateCollection.new(@machine)
27
+
28
+ @states << @nil = StateMachines::State.new(@machine, nil)
29
+ @states << @parked = StateMachines::State.new(@machine, :parked)
30
+ @states << @idling = StateMachines::State.new(@machine, :idling)
31
+ @machine.states.concat(@states)
32
+
33
+ @object = @klass.new
34
+ end
35
+
36
+ it 'should_index_by_name' do
37
+ assert_equal @parked, @states[:parked, :name]
38
+ end
39
+
40
+ it 'should_index_by_name_by_default' do
41
+ assert_equal @parked, @states[:parked]
42
+ end
43
+
44
+ it 'should_index_by_string_name' do
45
+ assert_equal @parked, @states['parked']
46
+ end
47
+
48
+ it 'should_index_by_qualified_name' do
49
+ assert_equal @parked, @states[:parked, :qualified_name]
50
+ end
51
+
52
+ it 'should_index_by_string_qualified_name' do
53
+ assert_equal @parked, @states['parked', :qualified_name]
54
+ end
55
+
56
+ it 'should_index_by_value' do
57
+ assert_equal @parked, @states['parked', :value]
58
+ end
59
+
60
+ it 'should_not_match_if_value_does_not_match' do
61
+ assert !@states.matches?(@object, :parked)
62
+ assert !@states.matches?(@object, :idling)
63
+ end
64
+
65
+ it 'should_match_if_value_matches' do
66
+ assert @states.matches?(@object, nil)
67
+ end
68
+
69
+ it 'raise_exception_if_matching_invalid_state' do
70
+ assert_raise(IndexError) { @states.matches?(@object, :invalid) }
71
+ end
72
+
73
+ it 'should_find_state_for_object_if_value_is_known' do
74
+ @object.state = 'parked'
75
+ assert_equal @parked, @states.match(@object)
76
+ end
77
+
78
+ it 'should_find_bang_state_for_object_if_value_is_known' do
79
+ @object.state = 'parked'
80
+ assert_equal @parked, @states.match!(@object)
81
+ end
82
+
83
+ it 'should_not_find_state_for_object_with_unknown_value' do
84
+ @object.state = 'invalid'
85
+ assert_nil @states.match(@object)
86
+ end
87
+
88
+ it 'should_raise_exception_if_finding_bang_state_for_object_with_unknown_value' do
89
+ @object.state = 'invalid'
90
+ assert_raise(ArgumentError) { @states.match!(@object) }
91
+ #assert_equal '"invalid" is not a known state value', exception.message
92
+ end
93
+ end
94
+
95
+ context 'String' do
96
+ before(:each) do
97
+ @klass = Class.new
98
+ @machine = StateMachines::Machine.new(@klass)
99
+ @states = StateMachines::StateCollection.new(@machine)
100
+
101
+ @states << @nil = StateMachines::State.new(@machine, nil)
102
+ @states << @parked = StateMachines::State.new(@machine, 'parked')
103
+ @machine.states.concat(@states)
104
+
105
+ @object = @klass.new
106
+ end
107
+
108
+ it 'should_index_by_name' do
109
+ assert_equal @parked, @states['parked', :name]
110
+ end
111
+
112
+ it 'should_index_by_name_by_default' do
113
+ assert_equal @parked, @states['parked']
114
+ end
115
+
116
+ it 'should_index_by_symbol_name' do
117
+ assert_equal @parked, @states[:parked]
118
+ end
119
+
120
+ it 'should_index_by_qualified_name' do
121
+ assert_equal @parked, @states['parked', :qualified_name]
122
+ end
123
+
124
+ it 'should_index_by_symbol_qualified_name' do
125
+ assert_equal @parked, @states[:parked, :qualified_name]
126
+ end
127
+ end
128
+
129
+ context 'WithNamespace' do
130
+ before(:each) do
131
+ @klass = Class.new
132
+ @machine = StateMachines::Machine.new(@klass, :namespace => 'vehicle')
133
+ @states = StateMachines::StateCollection.new(@machine)
134
+
135
+ @states << @state = StateMachines::State.new(@machine, :parked)
136
+ @machine.states.concat(@states)
137
+ end
138
+
139
+ it 'should_index_by_name' do
140
+ assert_equal @state, @states[:parked, :name]
141
+ end
142
+
143
+ it 'should_index_by_qualified_name' do
144
+ assert_equal @state, @states[:vehicle_parked, :qualified_name]
145
+ end
146
+ end
147
+
148
+ context 'WithCustomStateValues' do
149
+ before(:each) do
150
+ @klass = Class.new
151
+ @machine = StateMachines::Machine.new(@klass)
152
+ @states = StateMachines::StateCollection.new(@machine)
153
+
154
+ @states << @state = StateMachines::State.new(@machine, :parked, :value => 1)
155
+ @machine.states.concat(@states)
156
+
157
+ @object = @klass.new
158
+ @object.state = 1
159
+ end
160
+
161
+ it 'should_match_if_value_matches' do
162
+ assert @states.matches?(@object, :parked)
163
+ end
164
+
165
+ it 'should_not_match_if_value_does_not_match' do
166
+ @object.state = 2
167
+ assert !@states.matches?(@object, :parked)
168
+ end
169
+
170
+ it 'should_find_state_for_object_if_value_is_known' do
171
+ assert_equal @state, @states.match(@object)
172
+ end
173
+ end
174
+
175
+ context 'WithStateMatchers' do
176
+ before(:each) do
177
+ @klass = Class.new
178
+ @machine = StateMachines::Machine.new(@klass)
179
+ @states = StateMachines::StateCollection.new(@machine)
180
+
181
+ @states << @state = StateMachines::State.new(@machine, :parked, :if => lambda {|value| !value.nil?})
182
+ @machine.states.concat(@states)
183
+
184
+ @object = @klass.new
185
+ @object.state = 1
186
+ end
187
+
188
+ it 'should_match_if_value_matches' do
189
+ assert @states.matches?(@object, :parked)
190
+ end
191
+
192
+ it 'should_not_match_if_value_does_not_match' do
193
+ @object.state = nil
194
+ assert !@states.matches?(@object, :parked)
195
+ end
196
+
197
+ it 'should_find_state_for_object_if_value_is_known' do
198
+ assert_equal @state, @states.match(@object)
199
+ end
200
+ end
201
+
202
+ context 'WithInitialState' do
203
+ before(:each) do
204
+ @machine = StateMachines::Machine.new(Class.new)
205
+ @states = StateMachines::StateCollection.new(@machine)
206
+
207
+ @states << @parked = StateMachines::State.new(@machine, :parked)
208
+ @states << @idling = StateMachines::State.new(@machine, :idling)
209
+ @machine.states.concat(@states)
210
+
211
+ @parked.initial = true
212
+ end
213
+
214
+ it 'should_order_state_before_transition_states' do
215
+ @machine.event :ignite do
216
+ transition :to => :idling
217
+ end
218
+ assert_equal [@parked, @idling], @states.by_priority
219
+ end
220
+
221
+ it 'should_order_state_before_states_with_behaviors' do
222
+ @idling.context do
223
+ def speed
224
+ 0
225
+ end
226
+ end
227
+ assert_equal [@parked, @idling], @states.by_priority
228
+ end
229
+
230
+ it 'should_order_state_before_other_states' do
231
+ assert_equal [@parked, @idling], @states.by_priority
232
+ end
233
+
234
+ it 'should_order_state_before_callback_states' do
235
+ @machine.before_transition :from => :idling, :do => lambda {}
236
+ assert_equal [@parked, @idling], @states.by_priority
237
+ end
238
+ end
239
+
240
+ context 'WithStateBehaviors' do
241
+ before(:each) do
242
+ @machine = StateMachines::Machine.new(Class.new)
243
+ @states = StateMachines::StateCollection.new(@machine)
244
+
245
+ @states << @parked = StateMachines::State.new(@machine, :parked)
246
+ @states << @idling = StateMachines::State.new(@machine, :idling)
247
+ @machine.states.concat(@states)
248
+
249
+ @idling.context do
250
+ def speed
251
+ 0
252
+ end
253
+ end
254
+ end
255
+
256
+ it 'should_order_states_after_initial_state' do
257
+ @parked.initial = true
258
+ assert_equal [@parked, @idling], @states.by_priority
259
+ end
260
+
261
+ it 'should_order_states_after_transition_states' do
262
+ @machine.event :ignite do
263
+ transition :from => :parked
264
+ end
265
+ assert_equal [@parked, @idling], @states.by_priority
266
+ end
267
+
268
+ it 'should_order_states_before_other_states' do
269
+ assert_equal [@idling, @parked], @states.by_priority
270
+ end
271
+
272
+ it 'should_order_state_before_callback_states' do
273
+ @machine.before_transition :from => :parked, :do => lambda {}
274
+ assert_equal [@idling, @parked], @states.by_priority
275
+ end
276
+ end
277
+
278
+ context 'WithEventTransitions' do
279
+ before(:each) do
280
+ @machine = StateMachines::Machine.new(Class.new)
281
+ @states = StateMachines::StateCollection.new(@machine)
282
+
283
+ @states << @parked = StateMachines::State.new(@machine, :parked)
284
+ @states << @idling = StateMachines::State.new(@machine, :idling)
285
+ @machine.states.concat(@states)
286
+
287
+ @machine.event :ignite do
288
+ transition :to => :idling
289
+ end
290
+ end
291
+
292
+ it 'should_order_states_after_initial_state' do
293
+ @parked.initial = true
294
+ assert_equal [@parked, @idling], @states.by_priority
295
+ end
296
+
297
+ it 'should_order_states_before_states_with_behaviors' do
298
+ @parked.context do
299
+ def speed
300
+ 0
301
+ end
302
+ end
303
+ assert_equal [@idling, @parked], @states.by_priority
304
+ end
305
+
306
+ it 'should_order_states_before_other_states' do
307
+ assert_equal [@idling, @parked], @states.by_priority
308
+ end
309
+
310
+ it 'should_order_state_before_callback_states' do
311
+ @machine.before_transition :from => :parked, :do => lambda {}
312
+ assert_equal [@idling, @parked], @states.by_priority
313
+ end
314
+ end
315
+
316
+ context 'WithTransitionCallbacks' do
317
+ before(:each) do
318
+ @machine = StateMachines::Machine.new(Class.new)
319
+ @states = StateMachines::StateCollection.new(@machine)
320
+
321
+ @states << @parked = StateMachines::State.new(@machine, :parked)
322
+ @states << @idling = StateMachines::State.new(@machine, :idling)
323
+ @machine.states.concat(@states)
324
+
325
+ @machine.before_transition :to => :idling, :do => lambda {}
326
+ end
327
+
328
+ it 'should_order_states_after_initial_state' do
329
+ @parked.initial = true
330
+ assert_equal [@parked, @idling], @states.by_priority
331
+ end
332
+
333
+ it 'should_order_states_after_transition_states' do
334
+ @machine.event :ignite do
335
+ transition :from => :parked
336
+ end
337
+ assert_equal [@parked, @idling], @states.by_priority
338
+ end
339
+
340
+ it 'should_order_states_after_states_with_behaviors' do
341
+ @parked.context do
342
+ def speed
343
+ 0
344
+ end
345
+ end
346
+ assert_equal [@parked, @idling], @states.by_priority
347
+ end
348
+
349
+ it 'should_order_states_after_other_states' do
350
+ assert_equal [@parked, @idling], @states.by_priority
351
+ end
352
+ end