verborghs-state_machine 0.9.4

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