hsume2-state_machine 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/CHANGELOG.rdoc +413 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +717 -0
  4. data/Rakefile +77 -0
  5. data/examples/AutoShop_state.png +0 -0
  6. data/examples/Car_state.png +0 -0
  7. data/examples/TrafficLight_state.png +0 -0
  8. data/examples/Vehicle_state.png +0 -0
  9. data/examples/auto_shop.rb +11 -0
  10. data/examples/car.rb +19 -0
  11. data/examples/merb-rest/controller.rb +51 -0
  12. data/examples/merb-rest/model.rb +28 -0
  13. data/examples/merb-rest/view_edit.html.erb +24 -0
  14. data/examples/merb-rest/view_index.html.erb +23 -0
  15. data/examples/merb-rest/view_new.html.erb +13 -0
  16. data/examples/merb-rest/view_show.html.erb +17 -0
  17. data/examples/rails-rest/controller.rb +43 -0
  18. data/examples/rails-rest/migration.rb +11 -0
  19. data/examples/rails-rest/model.rb +23 -0
  20. data/examples/rails-rest/view_edit.html.erb +25 -0
  21. data/examples/rails-rest/view_index.html.erb +23 -0
  22. data/examples/rails-rest/view_new.html.erb +14 -0
  23. data/examples/rails-rest/view_show.html.erb +17 -0
  24. data/examples/traffic_light.rb +7 -0
  25. data/examples/vehicle.rb +31 -0
  26. data/init.rb +1 -0
  27. data/lib/state_machine.rb +448 -0
  28. data/lib/state_machine/alternate_machine.rb +79 -0
  29. data/lib/state_machine/assertions.rb +36 -0
  30. data/lib/state_machine/branch.rb +224 -0
  31. data/lib/state_machine/callback.rb +236 -0
  32. data/lib/state_machine/condition_proxy.rb +94 -0
  33. data/lib/state_machine/error.rb +13 -0
  34. data/lib/state_machine/eval_helpers.rb +86 -0
  35. data/lib/state_machine/event.rb +304 -0
  36. data/lib/state_machine/event_collection.rb +139 -0
  37. data/lib/state_machine/extensions.rb +149 -0
  38. data/lib/state_machine/initializers.rb +4 -0
  39. data/lib/state_machine/initializers/merb.rb +1 -0
  40. data/lib/state_machine/initializers/rails.rb +25 -0
  41. data/lib/state_machine/integrations.rb +110 -0
  42. data/lib/state_machine/integrations/active_model.rb +502 -0
  43. data/lib/state_machine/integrations/active_model/locale.rb +11 -0
  44. data/lib/state_machine/integrations/active_model/observer.rb +45 -0
  45. data/lib/state_machine/integrations/active_model/versions.rb +31 -0
  46. data/lib/state_machine/integrations/active_record.rb +424 -0
  47. data/lib/state_machine/integrations/active_record/locale.rb +20 -0
  48. data/lib/state_machine/integrations/active_record/versions.rb +143 -0
  49. data/lib/state_machine/integrations/base.rb +91 -0
  50. data/lib/state_machine/integrations/data_mapper.rb +392 -0
  51. data/lib/state_machine/integrations/data_mapper/observer.rb +210 -0
  52. data/lib/state_machine/integrations/data_mapper/versions.rb +62 -0
  53. data/lib/state_machine/integrations/mongo_mapper.rb +272 -0
  54. data/lib/state_machine/integrations/mongo_mapper/locale.rb +4 -0
  55. data/lib/state_machine/integrations/mongo_mapper/versions.rb +110 -0
  56. data/lib/state_machine/integrations/mongoid.rb +357 -0
  57. data/lib/state_machine/integrations/mongoid/locale.rb +4 -0
  58. data/lib/state_machine/integrations/mongoid/versions.rb +18 -0
  59. data/lib/state_machine/integrations/sequel.rb +428 -0
  60. data/lib/state_machine/integrations/sequel/versions.rb +36 -0
  61. data/lib/state_machine/machine.rb +1873 -0
  62. data/lib/state_machine/machine_collection.rb +87 -0
  63. data/lib/state_machine/matcher.rb +123 -0
  64. data/lib/state_machine/matcher_helpers.rb +54 -0
  65. data/lib/state_machine/node_collection.rb +157 -0
  66. data/lib/state_machine/path.rb +120 -0
  67. data/lib/state_machine/path_collection.rb +90 -0
  68. data/lib/state_machine/state.rb +271 -0
  69. data/lib/state_machine/state_collection.rb +112 -0
  70. data/lib/state_machine/transition.rb +458 -0
  71. data/lib/state_machine/transition_collection.rb +244 -0
  72. data/lib/tasks/state_machine.rake +1 -0
  73. data/lib/tasks/state_machine.rb +27 -0
  74. data/test/files/en.yml +17 -0
  75. data/test/files/switch.rb +11 -0
  76. data/test/functional/alternate_state_machine_test.rb +122 -0
  77. data/test/functional/state_machine_test.rb +993 -0
  78. data/test/test_helper.rb +4 -0
  79. data/test/unit/assertions_test.rb +40 -0
  80. data/test/unit/branch_test.rb +890 -0
  81. data/test/unit/callback_test.rb +701 -0
  82. data/test/unit/condition_proxy_test.rb +328 -0
  83. data/test/unit/error_test.rb +43 -0
  84. data/test/unit/eval_helpers_test.rb +222 -0
  85. data/test/unit/event_collection_test.rb +358 -0
  86. data/test/unit/event_test.rb +985 -0
  87. data/test/unit/integrations/active_model_test.rb +1097 -0
  88. data/test/unit/integrations/active_record_test.rb +2021 -0
  89. data/test/unit/integrations/base_test.rb +99 -0
  90. data/test/unit/integrations/data_mapper_test.rb +1909 -0
  91. data/test/unit/integrations/mongo_mapper_test.rb +1611 -0
  92. data/test/unit/integrations/mongoid_test.rb +1591 -0
  93. data/test/unit/integrations/sequel_test.rb +1523 -0
  94. data/test/unit/integrations_test.rb +61 -0
  95. data/test/unit/invalid_event_test.rb +20 -0
  96. data/test/unit/invalid_parallel_transition_test.rb +18 -0
  97. data/test/unit/invalid_transition_test.rb +77 -0
  98. data/test/unit/machine_collection_test.rb +599 -0
  99. data/test/unit/machine_test.rb +3043 -0
  100. data/test/unit/matcher_helpers_test.rb +37 -0
  101. data/test/unit/matcher_test.rb +155 -0
  102. data/test/unit/node_collection_test.rb +217 -0
  103. data/test/unit/path_collection_test.rb +266 -0
  104. data/test/unit/path_test.rb +485 -0
  105. data/test/unit/state_collection_test.rb +310 -0
  106. data/test/unit/state_machine_test.rb +31 -0
  107. data/test/unit/state_test.rb +924 -0
  108. data/test/unit/transition_collection_test.rb +2102 -0
  109. data/test/unit/transition_test.rb +1541 -0
  110. metadata +207 -0
@@ -0,0 +1,4 @@
1
+ require 'test/unit'
2
+
3
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
4
+ require File.dirname(__FILE__) + '/../init'
@@ -0,0 +1,40 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class AssertionsBaseTest < Test::Unit::TestCase
4
+ include StateMachine::Assertions
5
+
6
+ def default_test
7
+ end
8
+ end
9
+
10
+ class AssertValidKeysTest < AssertionsBaseTest
11
+ def test_should_not_raise_exception_if_key_is_valid
12
+ assert_nothing_raised { assert_valid_keys({:name => 'foo', :value => 'bar'}, :name, :value, :force) }
13
+ end
14
+
15
+ def test_should_raise_exception_if_key_is_invalid
16
+ exception = assert_raise(ArgumentError) { assert_valid_keys({:name => 'foo', :value => 'bar', :invalid => true}, :name, :value, :force) }
17
+ assert_equal 'Invalid key(s): invalid', exception.message
18
+ end
19
+ end
20
+
21
+ class AssertExclusiveKeysTest < AssertionsBaseTest
22
+ def test_should_not_raise_exception_if_no_keys_found
23
+ assert_nothing_raised { assert_exclusive_keys({:on => :park}, :only, :except) }
24
+ end
25
+
26
+ def test_should_not_raise_exception_if_one_key_found
27
+ assert_nothing_raised { assert_exclusive_keys({:only => :parked}, :only, :except) }
28
+ assert_nothing_raised { assert_exclusive_keys({:except => :parked}, :only, :except) }
29
+ end
30
+
31
+ def test_should_raise_exception_if_two_keys_found
32
+ exception = assert_raise(ArgumentError) { assert_exclusive_keys({:only => :parked, :except => :parked}, :only, :except) }
33
+ assert_equal 'Conflicting keys: only, except', exception.message
34
+ end
35
+
36
+ def test_should_raise_exception_if_multiple_keys_found
37
+ exception = assert_raise(ArgumentError) { assert_exclusive_keys({:only => :parked, :except => :parked, :on => :park}, :only, :except, :with) }
38
+ assert_equal 'Conflicting keys: only, except', exception.message
39
+ end
40
+ end
@@ -0,0 +1,890 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class BranchTest < Test::Unit::TestCase
4
+ def setup
5
+ @branch = StateMachine::Branch.new(:from => :parked, :to => :idling)
6
+ end
7
+
8
+ def test_should_not_raise_exception_if_implicit_option_specified
9
+ assert_nothing_raised { StateMachine::Branch.new(:invalid => :valid) }
10
+ end
11
+
12
+ def test_should_not_have_an_if_condition
13
+ assert_nil @branch.if_condition
14
+ end
15
+
16
+ def test_should_not_have_an_unless_condition
17
+ assert_nil @branch.unless_condition
18
+ end
19
+
20
+ def test_should_have_a_state_requirement
21
+ assert_equal 1, @branch.state_requirements.length
22
+ end
23
+
24
+ def test_should_raise_an_exception_if_invalid_match_option_specified
25
+ exception = assert_raise(ArgumentError) { @branch.match(Object.new, :invalid => true) }
26
+ assert_equal 'Invalid key(s): invalid', exception.message
27
+ end
28
+ end
29
+
30
+ class BranchWithNoRequirementsTest < Test::Unit::TestCase
31
+ def setup
32
+ @object = Object.new
33
+ @branch = StateMachine::Branch.new
34
+ end
35
+
36
+ def test_should_use_all_matcher_for_event_requirement
37
+ assert_equal StateMachine::AllMatcher.instance, @branch.event_requirement
38
+ end
39
+
40
+ def test_should_use_all_matcher_for_from_state_requirement
41
+ assert_equal StateMachine::AllMatcher.instance, @branch.state_requirements.first[:from]
42
+ end
43
+
44
+ def test_should_use_all_matcher_for_to_state_requirement
45
+ assert_equal StateMachine::AllMatcher.instance, @branch.state_requirements.first[:to]
46
+ end
47
+
48
+ def test_should_match_empty_query
49
+ assert @branch.matches?(@object, {})
50
+ end
51
+
52
+ def test_should_match_non_empty_query
53
+ assert @branch.matches?(@object, :to => :idling, :from => :parked, :on => :ignite)
54
+ end
55
+
56
+ def test_should_include_all_requirements_in_match
57
+ match = @branch.match(@object, {})
58
+
59
+ assert_equal @branch.state_requirements.first[:from], match[:from]
60
+ assert_equal @branch.state_requirements.first[:to], match[:to]
61
+ assert_equal @branch.event_requirement, match[:on]
62
+ end
63
+ end
64
+
65
+ class BranchWithFromRequirementTest < Test::Unit::TestCase
66
+ def setup
67
+ @object = Object.new
68
+ @branch = StateMachine::Branch.new(:from => :parked)
69
+ end
70
+
71
+ def test_should_use_a_whitelist_matcher
72
+ assert_instance_of StateMachine::WhitelistMatcher, @branch.state_requirements.first[:from]
73
+ end
74
+
75
+ def test_should_match_if_not_specified
76
+ assert @branch.matches?(@object, :to => :idling)
77
+ end
78
+
79
+ def test_should_match_if_included
80
+ assert @branch.matches?(@object, :from => :parked)
81
+ end
82
+
83
+ def test_should_not_match_if_not_included
84
+ assert !@branch.matches?(@object, :from => :idling)
85
+ end
86
+
87
+ def test_should_not_match_if_nil
88
+ assert !@branch.matches?(@object, :from => nil)
89
+ end
90
+
91
+ def test_should_ignore_to
92
+ assert @branch.matches?(@object, :from => :parked, :to => :idling)
93
+ end
94
+
95
+ def test_should_ignore_on
96
+ assert @branch.matches?(@object, :from => :parked, :on => :ignite)
97
+ end
98
+
99
+ def test_should_be_included_in_known_states
100
+ assert_equal [:parked], @branch.known_states
101
+ end
102
+
103
+ def test_should_include_requirement_in_match
104
+ match = @branch.match(@object, :from => :parked)
105
+ assert_equal @branch.state_requirements.first[:from], match[:from]
106
+ end
107
+ end
108
+
109
+ class BranchWithMultipleFromRequirementsTest < Test::Unit::TestCase
110
+ def setup
111
+ @object = Object.new
112
+ @branch = StateMachine::Branch.new(:from => [:idling, :parked])
113
+ end
114
+
115
+ def test_should_match_if_included
116
+ assert @branch.matches?(@object, :from => :idling)
117
+ end
118
+
119
+ def test_should_not_match_if_not_included
120
+ assert !@branch.matches?(@object, :from => :first_gear)
121
+ end
122
+
123
+ def test_should_be_included_in_known_states
124
+ assert_equal [:idling, :parked], @branch.known_states
125
+ end
126
+ end
127
+
128
+ class BranchWithToRequirementTest < Test::Unit::TestCase
129
+ def setup
130
+ @object = Object.new
131
+ @branch = StateMachine::Branch.new(:to => :idling)
132
+ end
133
+
134
+ def test_should_use_a_whitelist_matcher
135
+ assert_instance_of StateMachine::WhitelistMatcher, @branch.state_requirements.first[:to]
136
+ end
137
+
138
+ def test_should_match_if_not_specified
139
+ assert @branch.matches?(@object, :from => :parked)
140
+ end
141
+
142
+ def test_should_match_if_included
143
+ assert @branch.matches?(@object, :to => :idling)
144
+ end
145
+
146
+ def test_should_not_match_if_not_included
147
+ assert !@branch.matches?(@object, :to => :parked)
148
+ end
149
+
150
+ def test_should_not_match_if_nil
151
+ assert !@branch.matches?(@object, :to => nil)
152
+ end
153
+
154
+ def test_should_ignore_from
155
+ assert @branch.matches?(@object, :to => :idling, :from => :parked)
156
+ end
157
+
158
+ def test_should_ignore_on
159
+ assert @branch.matches?(@object, :to => :idling, :on => :ignite)
160
+ end
161
+
162
+ def test_should_be_included_in_known_states
163
+ assert_equal [:idling], @branch.known_states
164
+ end
165
+
166
+ def test_should_include_requirement_in_match
167
+ match = @branch.match(@object, :to => :idling)
168
+ assert_equal @branch.state_requirements.first[:to], match[:to]
169
+ end
170
+ end
171
+
172
+ class BranchWithMultipleToRequirementsTest < Test::Unit::TestCase
173
+ def setup
174
+ @object = Object.new
175
+ @branch = StateMachine::Branch.new(:to => [:idling, :parked])
176
+ end
177
+
178
+ def test_should_match_if_included
179
+ assert @branch.matches?(@object, :to => :idling)
180
+ end
181
+
182
+ def test_should_not_match_if_not_included
183
+ assert !@branch.matches?(@object, :to => :first_gear)
184
+ end
185
+
186
+ def test_should_be_included_in_known_states
187
+ assert_equal [:idling, :parked], @branch.known_states
188
+ end
189
+ end
190
+
191
+ class BranchWithOnRequirementTest < Test::Unit::TestCase
192
+ def setup
193
+ @object = Object.new
194
+ @branch = StateMachine::Branch.new(:on => :ignite)
195
+ end
196
+
197
+ def test_should_use_a_whitelist_matcher
198
+ assert_instance_of StateMachine::WhitelistMatcher, @branch.event_requirement
199
+ end
200
+
201
+ def test_should_match_if_not_specified
202
+ assert @branch.matches?(@object, :from => :parked)
203
+ end
204
+
205
+ def test_should_match_if_included
206
+ assert @branch.matches?(@object, :on => :ignite)
207
+ end
208
+
209
+ def test_should_not_match_if_not_included
210
+ assert !@branch.matches?(@object, :on => :park)
211
+ end
212
+
213
+ def test_should_not_match_if_nil
214
+ assert !@branch.matches?(@object, :on => nil)
215
+ end
216
+
217
+ def test_should_ignore_to
218
+ assert @branch.matches?(@object, :on => :ignite, :to => :parked)
219
+ end
220
+
221
+ def test_should_ignore_from
222
+ assert @branch.matches?(@object, :on => :ignite, :from => :parked)
223
+ end
224
+
225
+ def test_should_not_be_included_in_known_states
226
+ assert_equal [], @branch.known_states
227
+ end
228
+
229
+ def test_should_include_requirement_in_match
230
+ match = @branch.match(@object, :on => :ignite)
231
+ assert_equal @branch.event_requirement, match[:on]
232
+ end
233
+ end
234
+
235
+ class BranchWithMultipleOnRequirementsTest < Test::Unit::TestCase
236
+ def setup
237
+ @object = Object.new
238
+ @branch = StateMachine::Branch.new(:on => [:ignite, :park])
239
+ end
240
+
241
+ def test_should_match_if_included
242
+ assert @branch.matches?(@object, :on => :ignite)
243
+ end
244
+
245
+ def test_should_not_match_if_not_included
246
+ assert !@branch.matches?(@object, :on => :shift_up)
247
+ end
248
+ end
249
+
250
+ class BranchWithExceptFromRequirementTest < Test::Unit::TestCase
251
+ def setup
252
+ @object = Object.new
253
+ @branch = StateMachine::Branch.new(:except_from => :parked)
254
+ end
255
+
256
+ def test_should_use_a_blacklist_matcher
257
+ assert_instance_of StateMachine::BlacklistMatcher, @branch.state_requirements.first[:from]
258
+ end
259
+
260
+ def test_should_match_if_not_included
261
+ assert @branch.matches?(@object, :from => :idling)
262
+ end
263
+
264
+ def test_should_not_match_if_included
265
+ assert !@branch.matches?(@object, :from => :parked)
266
+ end
267
+
268
+ def test_should_match_if_nil
269
+ assert @branch.matches?(@object, :from => nil)
270
+ end
271
+
272
+ def test_should_ignore_to
273
+ assert @branch.matches?(@object, :from => :idling, :to => :parked)
274
+ end
275
+
276
+ def test_should_ignore_on
277
+ assert @branch.matches?(@object, :from => :idling, :on => :ignite)
278
+ end
279
+
280
+ def test_should_be_included_in_known_states
281
+ assert_equal [:parked], @branch.known_states
282
+ end
283
+ end
284
+
285
+ class BranchWithMultipleExceptFromRequirementsTest < Test::Unit::TestCase
286
+ def setup
287
+ @object = Object.new
288
+ @branch = StateMachine::Branch.new(:except_from => [:idling, :parked])
289
+ end
290
+
291
+ def test_should_match_if_not_included
292
+ assert @branch.matches?(@object, :from => :first_gear)
293
+ end
294
+
295
+ def test_should_not_match_if_included
296
+ assert !@branch.matches?(@object, :from => :idling)
297
+ end
298
+
299
+ def test_should_be_included_in_known_states
300
+ assert_equal [:idling, :parked], @branch.known_states
301
+ end
302
+ end
303
+
304
+ class BranchWithExceptToRequirementTest < Test::Unit::TestCase
305
+ def setup
306
+ @object = Object.new
307
+ @branch = StateMachine::Branch.new(:except_to => :idling)
308
+ end
309
+
310
+ def test_should_use_a_blacklist_matcher
311
+ assert_instance_of StateMachine::BlacklistMatcher, @branch.state_requirements.first[:to]
312
+ end
313
+
314
+ def test_should_match_if_not_included
315
+ assert @branch.matches?(@object, :to => :parked)
316
+ end
317
+
318
+ def test_should_not_match_if_included
319
+ assert !@branch.matches?(@object, :to => :idling)
320
+ end
321
+
322
+ def test_should_match_if_nil
323
+ assert @branch.matches?(@object, :to => nil)
324
+ end
325
+
326
+ def test_should_ignore_from
327
+ assert @branch.matches?(@object, :to => :parked, :from => :idling)
328
+ end
329
+
330
+ def test_should_ignore_on
331
+ assert @branch.matches?(@object, :to => :parked, :on => :ignite)
332
+ end
333
+
334
+ def test_should_be_included_in_known_states
335
+ assert_equal [:idling], @branch.known_states
336
+ end
337
+ end
338
+
339
+ class BranchWithMultipleExceptToRequirementsTest < Test::Unit::TestCase
340
+ def setup
341
+ @object = Object.new
342
+ @branch = StateMachine::Branch.new(:except_to => [:idling, :parked])
343
+ end
344
+
345
+ def test_should_match_if_not_included
346
+ assert @branch.matches?(@object, :to => :first_gear)
347
+ end
348
+
349
+ def test_should_not_match_if_included
350
+ assert !@branch.matches?(@object, :to => :idling)
351
+ end
352
+
353
+ def test_should_be_included_in_known_states
354
+ assert_equal [:idling, :parked], @branch.known_states
355
+ end
356
+ end
357
+
358
+ class BranchWithExceptOnRequirementTest < Test::Unit::TestCase
359
+ def setup
360
+ @object = Object.new
361
+ @branch = StateMachine::Branch.new(:except_on => :ignite)
362
+ end
363
+
364
+ def test_should_use_a_blacklist_matcher
365
+ assert_instance_of StateMachine::BlacklistMatcher, @branch.event_requirement
366
+ end
367
+
368
+ def test_should_match_if_not_included
369
+ assert @branch.matches?(@object, :on => :park)
370
+ end
371
+
372
+ def test_should_not_match_if_included
373
+ assert !@branch.matches?(@object, :on => :ignite)
374
+ end
375
+
376
+ def test_should_match_if_nil
377
+ assert @branch.matches?(@object, :on => nil)
378
+ end
379
+
380
+ def test_should_ignore_to
381
+ assert @branch.matches?(@object, :on => :park, :to => :idling)
382
+ end
383
+
384
+ def test_should_ignore_from
385
+ assert @branch.matches?(@object, :on => :park, :from => :parked)
386
+ end
387
+
388
+ def test_should_not_be_included_in_known_states
389
+ assert_equal [], @branch.known_states
390
+ end
391
+ end
392
+
393
+ class BranchWithMultipleExceptOnRequirementsTest < Test::Unit::TestCase
394
+ def setup
395
+ @object = Object.new
396
+ @branch = StateMachine::Branch.new(:except_on => [:ignite, :park])
397
+ end
398
+
399
+ def test_should_match_if_not_included
400
+ assert @branch.matches?(@object, :on => :shift_up)
401
+ end
402
+
403
+ def test_should_not_match_if_included
404
+ assert !@branch.matches?(@object, :on => :ignite)
405
+ end
406
+ end
407
+
408
+ class BranchWithConflictingFromRequirementsTest < Test::Unit::TestCase
409
+ def test_should_raise_an_exception
410
+ exception = assert_raise(ArgumentError) { StateMachine::Branch.new(:from => :parked, :except_from => :parked) }
411
+ assert_equal 'Conflicting keys: from, except_from', exception.message
412
+ end
413
+ end
414
+
415
+ class BranchWithConflictingToRequirementsTest < Test::Unit::TestCase
416
+ def test_should_raise_an_exception
417
+ exception = assert_raise(ArgumentError) { StateMachine::Branch.new(:to => :idling, :except_to => :idling) }
418
+ assert_equal 'Conflicting keys: to, except_to', exception.message
419
+ end
420
+ end
421
+
422
+ class BranchWithConflictingOnRequirementsTest < Test::Unit::TestCase
423
+ def test_should_raise_an_exception
424
+ exception = assert_raise(ArgumentError) { StateMachine::Branch.new(:on => :ignite, :except_on => :ignite) }
425
+ assert_equal 'Conflicting keys: on, except_on', exception.message
426
+ end
427
+ end
428
+
429
+ class BranchWithDifferentRequirementsTest < Test::Unit::TestCase
430
+ def setup
431
+ @object = Object.new
432
+ @branch = StateMachine::Branch.new(:from => :parked, :to => :idling, :on => :ignite)
433
+ end
434
+
435
+ def test_should_match_empty_query
436
+ assert @branch.matches?(@object)
437
+ end
438
+
439
+ def test_should_match_if_all_requirements_match
440
+ assert @branch.matches?(@object, :from => :parked, :to => :idling, :on => :ignite)
441
+ end
442
+
443
+ def test_should_not_match_if_from_not_included
444
+ assert !@branch.matches?(@object, :from => :idling)
445
+ end
446
+
447
+ def test_should_not_match_if_to_not_included
448
+ assert !@branch.matches?(@object, :to => :parked)
449
+ end
450
+
451
+ def test_should_not_match_if_on_not_included
452
+ assert !@branch.matches?(@object, :on => :park)
453
+ end
454
+
455
+ def test_should_be_nil_if_unmatched
456
+ assert_nil @branch.match(@object, :from => :parked, :to => :idling, :on => :park)
457
+ end
458
+
459
+ def test_should_include_all_known_states
460
+ assert_equal [:parked, :idling], @branch.known_states
461
+ end
462
+
463
+ def test_should_not_duplicate_known_statse
464
+ branch = StateMachine::Branch.new(:except_from => :idling, :to => :idling, :on => :ignite)
465
+ assert_equal [:idling], branch.known_states
466
+ end
467
+ end
468
+
469
+ class BranchWithNilRequirementsTest < Test::Unit::TestCase
470
+ def setup
471
+ @object = Object.new
472
+ @branch = StateMachine::Branch.new(:from => nil, :to => nil)
473
+ end
474
+
475
+ def test_should_match_empty_query
476
+ assert @branch.matches?(@object)
477
+ end
478
+
479
+ def test_should_match_if_all_requirements_match
480
+ assert @branch.matches?(@object, :from => nil, :to => nil)
481
+ end
482
+
483
+ def test_should_not_match_if_from_not_included
484
+ assert !@branch.matches?(@object, :from => :parked)
485
+ end
486
+
487
+ def test_should_not_match_if_to_not_included
488
+ assert !@branch.matches?(@object, :to => :idling)
489
+ end
490
+
491
+ def test_should_include_all_known_states
492
+ assert_equal [nil], @branch.known_states
493
+ end
494
+ end
495
+
496
+ class BranchWithImplicitRequirementTest < Test::Unit::TestCase
497
+ def setup
498
+ @branch = StateMachine::Branch.new(:parked => :idling, :on => :ignite)
499
+ end
500
+
501
+ def test_should_create_an_event_requirement
502
+ assert_instance_of StateMachine::WhitelistMatcher, @branch.event_requirement
503
+ assert_equal [:ignite], @branch.event_requirement.values
504
+ end
505
+
506
+ def test_should_use_a_whitelist_from_matcher
507
+ assert_instance_of StateMachine::WhitelistMatcher, @branch.state_requirements.first[:from]
508
+ end
509
+
510
+ def test_should_use_a_whitelist_to_matcher
511
+ assert_instance_of StateMachine::WhitelistMatcher, @branch.state_requirements.first[:to]
512
+ end
513
+ end
514
+
515
+ class BranchWithMultipleImplicitRequirementsTest < Test::Unit::TestCase
516
+ def setup
517
+ @object = Object.new
518
+ @branch = StateMachine::Branch.new(:parked => :idling, :idling => :first_gear, :on => :ignite)
519
+ end
520
+
521
+ def test_should_create_multiple_state_requirements
522
+ assert_equal 2, @branch.state_requirements.length
523
+ end
524
+
525
+ def test_should_not_match_event_as_state_requirement
526
+ assert !@branch.matches?(@object, :from => :on, :to => :ignite)
527
+ end
528
+
529
+ def test_should_match_if_from_included_in_any
530
+ assert @branch.matches?(@object, :from => :parked)
531
+ assert @branch.matches?(@object, :from => :idling)
532
+ end
533
+
534
+ def test_should_not_match_if_from_not_included_in_any
535
+ assert !@branch.matches?(@object, :from => :first_gear)
536
+ end
537
+
538
+ def test_should_match_if_to_included_in_any
539
+ assert @branch.matches?(@object, :to => :idling)
540
+ assert @branch.matches?(@object, :to => :first_gear)
541
+ end
542
+
543
+ def test_should_not_match_if_to_not_included_in_any
544
+ assert !@branch.matches?(@object, :to => :parked)
545
+ end
546
+
547
+ def test_should_match_if_all_options_match
548
+ assert @branch.matches?(@object, :from => :parked, :to => :idling, :on => :ignite)
549
+ assert @branch.matches?(@object, :from => :idling, :to => :first_gear, :on => :ignite)
550
+ end
551
+
552
+ def test_should_not_match_if_any_options_do_not_match
553
+ assert !@branch.matches?(@object, :from => :parked, :to => :idling, :on => :park)
554
+ assert !@branch.matches?(@object, :from => :parked, :to => :first_gear, :on => :park)
555
+ end
556
+
557
+ def test_should_include_all_known_states
558
+ assert_equal [:first_gear, :idling, :parked], @branch.known_states.sort_by {|state| state.to_s}
559
+ end
560
+
561
+ def test_should_not_duplicate_known_statse
562
+ branch = StateMachine::Branch.new(:parked => :idling, :first_gear => :idling)
563
+ assert_equal [:first_gear, :idling, :parked], branch.known_states.sort_by {|state| state.to_s}
564
+ end
565
+ end
566
+
567
+ class BranchWithImplicitFromRequirementMatcherTest < Test::Unit::TestCase
568
+ def setup
569
+ @matcher = StateMachine::BlacklistMatcher.new(:parked)
570
+ @branch = StateMachine::Branch.new(@matcher => :idling)
571
+ end
572
+
573
+ def test_should_not_convert_from_to_whitelist_matcher
574
+ assert_equal @matcher, @branch.state_requirements.first[:from]
575
+ end
576
+
577
+ def test_should_convert_to_to_whitelist_matcher
578
+ assert_instance_of StateMachine::WhitelistMatcher, @branch.state_requirements.first[:to]
579
+ end
580
+ end
581
+
582
+ class BranchWithImplicitToRequirementMatcherTest < Test::Unit::TestCase
583
+ def setup
584
+ @matcher = StateMachine::BlacklistMatcher.new(:idling)
585
+ @branch = StateMachine::Branch.new(:parked => @matcher)
586
+ end
587
+
588
+ def test_should_convert_from_to_whitelist_matcher
589
+ assert_instance_of StateMachine::WhitelistMatcher, @branch.state_requirements.first[:from]
590
+ end
591
+
592
+ def test_should_not_convert_to_to_whitelist_matcher
593
+ assert_equal @matcher, @branch.state_requirements.first[:to]
594
+ end
595
+ end
596
+
597
+ class BranchWithImplicitAndExplicitRequirementsTest < Test::Unit::TestCase
598
+ def setup
599
+ @branch = StateMachine::Branch.new(:parked => :idling, :from => :parked)
600
+ end
601
+
602
+ def test_should_create_multiple_requirements
603
+ assert_equal 2, @branch.state_requirements.length
604
+ end
605
+
606
+ def test_should_create_implicit_requirements_for_implicit_options
607
+ assert(@branch.state_requirements.any? do |state_requirement|
608
+ state_requirement[:from].values == [:parked] && state_requirement[:to].values == [:idling]
609
+ end)
610
+ end
611
+
612
+ def test_should_create_implicit_requirements_for_explicit_options
613
+ assert(@branch.state_requirements.any? do |state_requirement|
614
+ state_requirement[:from].values == [:from] && state_requirement[:to].values == [:parked]
615
+ end)
616
+ end
617
+ end
618
+
619
+ class BranchWithIfConditionalTest < Test::Unit::TestCase
620
+ def setup
621
+ @object = Object.new
622
+ end
623
+
624
+ def test_should_have_an_if_condition
625
+ branch = StateMachine::Branch.new(:if => lambda {true})
626
+ assert_not_nil branch.if_condition
627
+ end
628
+
629
+ def test_should_match_if_true
630
+ branch = StateMachine::Branch.new(:if => lambda {true})
631
+ assert branch.matches?(@object)
632
+ end
633
+
634
+ def test_should_not_match_if_false
635
+ branch = StateMachine::Branch.new(:if => lambda {false})
636
+ assert !branch.matches?(@object)
637
+ end
638
+
639
+ def test_should_be_nil_if_unmatched
640
+ branch = StateMachine::Branch.new(:if => lambda {false})
641
+ assert_nil branch.match(@object)
642
+ end
643
+ end
644
+
645
+ class BranchWithMultipleIfConditionalsTest < Test::Unit::TestCase
646
+ def setup
647
+ @object = Object.new
648
+ end
649
+
650
+ def test_should_match_if_all_are_true
651
+ branch = StateMachine::Branch.new(:if => [lambda {true}, lambda {true}])
652
+ assert branch.match(@object)
653
+ end
654
+
655
+ def test_should_not_match_if_any_are_false
656
+ branch = StateMachine::Branch.new(:if => [lambda {true}, lambda {false}])
657
+ assert !branch.match(@object)
658
+
659
+ branch = StateMachine::Branch.new(:if => [lambda {false}, lambda {true}])
660
+ assert !branch.match(@object)
661
+ end
662
+ end
663
+
664
+ class BranchWithUnlessConditionalTest < Test::Unit::TestCase
665
+ def setup
666
+ @object = Object.new
667
+ end
668
+
669
+ def test_should_have_an_unless_condition
670
+ branch = StateMachine::Branch.new(:unless => lambda {true})
671
+ assert_not_nil branch.unless_condition
672
+ end
673
+
674
+ def test_should_match_if_false
675
+ branch = StateMachine::Branch.new(:unless => lambda {false})
676
+ assert branch.matches?(@object)
677
+ end
678
+
679
+ def test_should_not_match_if_true
680
+ branch = StateMachine::Branch.new(:unless => lambda {true})
681
+ assert !branch.matches?(@object)
682
+ end
683
+
684
+ def test_should_be_nil_if_unmatched
685
+ branch = StateMachine::Branch.new(:unless => lambda {true})
686
+ assert_nil branch.match(@object)
687
+ end
688
+ end
689
+
690
+ class BranchWithMultipleUnlessConditionalsTest < Test::Unit::TestCase
691
+ def setup
692
+ @object = Object.new
693
+ end
694
+
695
+ def test_should_match_if_all_are_false
696
+ branch = StateMachine::Branch.new(:unless => [lambda {false}, lambda {false}])
697
+ assert branch.match(@object)
698
+ end
699
+
700
+ def test_should_not_match_if_any_are_true
701
+ branch = StateMachine::Branch.new(:unless => [lambda {true}, lambda {false}])
702
+ assert !branch.match(@object)
703
+
704
+ branch = StateMachine::Branch.new(:unless => [lambda {false}, lambda {true}])
705
+ assert !branch.match(@object)
706
+ end
707
+ end
708
+
709
+ class BranchWithConflictingConditionalsTest < Test::Unit::TestCase
710
+ def test_should_match_if_if_is_true_and_unless_is_false
711
+ branch = StateMachine::Branch.new(:if => lambda {true}, :unless => lambda {false})
712
+ assert branch.match(@object)
713
+ end
714
+
715
+ def test_should_not_match_if_if_is_false_and_unless_is_true
716
+ branch = StateMachine::Branch.new(:if => lambda {false}, :unless => lambda {true})
717
+ assert !branch.match(@object)
718
+ end
719
+
720
+ def test_should_not_match_if_if_is_false_and_unless_is_false
721
+ branch = StateMachine::Branch.new(:if => lambda {false}, :unless => lambda {false})
722
+ assert !branch.match(@object)
723
+ end
724
+
725
+ def test_should_not_match_if_if_is_true_and_unless_is_true
726
+ branch = StateMachine::Branch.new(:if => lambda {true}, :unless => lambda {true})
727
+ assert !branch.match(@object)
728
+ end
729
+ end
730
+
731
+ class BranchWithoutGuardsTest < Test::Unit::TestCase
732
+ def setup
733
+ @object = Object.new
734
+ end
735
+
736
+ def test_should_match_if_if_is_false
737
+ branch = StateMachine::Branch.new(:if => lambda {false})
738
+ assert branch.matches?(@object, :guard => false)
739
+ end
740
+
741
+ def test_should_match_if_if_is_true
742
+ branch = StateMachine::Branch.new(:if => lambda {true})
743
+ assert branch.matches?(@object, :guard => false)
744
+ end
745
+
746
+ def test_should_match_if_unless_is_false
747
+ branch = StateMachine::Branch.new(:unless => lambda {false})
748
+ assert branch.matches?(@object, :guard => false)
749
+ end
750
+
751
+ def test_should_match_if_unless_is_true
752
+ branch = StateMachine::Branch.new(:unless => lambda {true})
753
+ assert branch.matches?(@object, :guard => false)
754
+ end
755
+ end
756
+
757
+ begin
758
+ # Load library
759
+ require 'rubygems'
760
+ gem 'ruby-graphviz', '>=0.9.0'
761
+ require 'graphviz'
762
+
763
+ class BranchDrawingTest < Test::Unit::TestCase
764
+ def setup
765
+ @machine = StateMachine::Machine.new(Class.new)
766
+ states = [:parked, :idling]
767
+
768
+ graph = GraphViz.new('G')
769
+ states.each {|state| graph.add_node(state.to_s)}
770
+
771
+ @branch = StateMachine::Branch.new(:from => :idling, :to => :parked)
772
+ @edges = @branch.draw(graph, :park, states)
773
+ end
774
+
775
+ def test_should_create_edges
776
+ assert_equal 1, @edges.size
777
+ end
778
+
779
+ def test_should_use_from_state_from_start_node
780
+ assert_equal 'idling', @edges.first.instance_variable_get('@xNodeOne')
781
+ end
782
+
783
+ def test_should_use_to_state_for_end_node
784
+ assert_equal 'parked', @edges.first.instance_variable_get('@xNodeTwo')
785
+ end
786
+
787
+ def test_should_use_event_name_as_label
788
+ assert_equal 'park', @edges.first['label'].to_s.gsub('"', '')
789
+ end
790
+ end
791
+
792
+ class BranchDrawingWithFromRequirementTest < Test::Unit::TestCase
793
+ def setup
794
+ @machine = StateMachine::Machine.new(Class.new)
795
+ states = [:parked, :idling, :first_gear]
796
+
797
+ graph = GraphViz.new('G')
798
+ states.each {|state| graph.add_node(state.to_s)}
799
+
800
+ @branch = StateMachine::Branch.new(:from => [:idling, :first_gear], :to => :parked)
801
+ @edges = @branch.draw(graph, :park, states)
802
+ end
803
+
804
+ def test_should_generate_edges_for_each_valid_from_state
805
+ [:idling, :first_gear].each_with_index do |from_state, index|
806
+ edge = @edges[index]
807
+ assert_equal from_state.to_s, edge.instance_variable_get('@xNodeOne')
808
+ assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
809
+ end
810
+ end
811
+ end
812
+
813
+ class BranchDrawingWithExceptFromRequirementTest < Test::Unit::TestCase
814
+ def setup
815
+ @machine = StateMachine::Machine.new(Class.new)
816
+ states = [:parked, :idling, :first_gear]
817
+
818
+ graph = GraphViz.new('G')
819
+ states.each {|state| graph.add_node(state.to_s)}
820
+
821
+ @branch = StateMachine::Branch.new(:except_from => :parked, :to => :parked)
822
+ @edges = @branch.draw(graph, :park, states)
823
+ end
824
+
825
+ def test_should_generate_edges_for_each_valid_from_state
826
+ %w(idling first_gear).each_with_index do |from_state, index|
827
+ edge = @edges[index]
828
+ assert_equal from_state, edge.instance_variable_get('@xNodeOne')
829
+ assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
830
+ end
831
+ end
832
+ end
833
+
834
+ class BranchDrawingWithoutFromRequirementTest < Test::Unit::TestCase
835
+ def setup
836
+ @machine = StateMachine::Machine.new(Class.new)
837
+ states = [:parked, :idling, :first_gear]
838
+
839
+ graph = GraphViz.new('G')
840
+ states.each {|state| graph.add_node(state.to_s)}
841
+
842
+ @branch = StateMachine::Branch.new(:to => :parked)
843
+ @edges = @branch.draw(graph, :park, states)
844
+ end
845
+
846
+ def test_should_generate_edges_for_each_valid_from_state
847
+ %w(parked idling first_gear).each_with_index do |from_state, index|
848
+ edge = @edges[index]
849
+ assert_equal from_state, edge.instance_variable_get('@xNodeOne')
850
+ assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
851
+ end
852
+ end
853
+ end
854
+
855
+ class BranchDrawingWithoutToRequirementTest < Test::Unit::TestCase
856
+ def setup
857
+ @machine = StateMachine::Machine.new(Class.new)
858
+
859
+ graph = GraphViz.new('G')
860
+ graph.add_node('parked')
861
+
862
+ @branch = StateMachine::Branch.new(:from => :parked)
863
+ @edges = @branch.draw(graph, :park, [:parked])
864
+ end
865
+
866
+ def test_should_create_loopback_edge
867
+ assert_equal 'parked', @edges.first.instance_variable_get('@xNodeOne')
868
+ assert_equal 'parked', @edges.first.instance_variable_get('@xNodeTwo')
869
+ end
870
+ end
871
+
872
+ class BranchDrawingWithNilStateTest < Test::Unit::TestCase
873
+ def setup
874
+ @machine = StateMachine::Machine.new(Class.new)
875
+
876
+ graph = GraphViz.new('G')
877
+ graph.add_node('parked')
878
+
879
+ @branch = StateMachine::Branch.new(:from => :idling, :to => nil)
880
+ @edges = @branch.draw(graph, :park, [nil, :idling])
881
+ end
882
+
883
+ def test_should_generate_edges_for_each_valid_from_state
884
+ assert_equal 'idling', @edges.first.instance_variable_get('@xNodeOne')
885
+ assert_equal 'nil', @edges.first.instance_variable_get('@xNodeTwo')
886
+ end
887
+ end
888
+ rescue LoadError
889
+ $stderr.puts 'Skipping GraphViz StateMachine::Branch tests. `gem install ruby-graphviz` >= v0.9.0 and try again.'
890
+ end