pluginaweek-state_machine 0.7.6

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 (78) hide show
  1. data/CHANGELOG.rdoc +273 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +466 -0
  4. data/Rakefile +98 -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 +429 -0
  28. data/lib/state_machine/assertions.rb +36 -0
  29. data/lib/state_machine/callback.rb +189 -0
  30. data/lib/state_machine/condition_proxy.rb +94 -0
  31. data/lib/state_machine/eval_helpers.rb +67 -0
  32. data/lib/state_machine/event.rb +251 -0
  33. data/lib/state_machine/event_collection.rb +113 -0
  34. data/lib/state_machine/extensions.rb +158 -0
  35. data/lib/state_machine/guard.rb +219 -0
  36. data/lib/state_machine/integrations.rb +68 -0
  37. data/lib/state_machine/integrations/active_record.rb +444 -0
  38. data/lib/state_machine/integrations/active_record/locale.rb +10 -0
  39. data/lib/state_machine/integrations/active_record/observer.rb +41 -0
  40. data/lib/state_machine/integrations/data_mapper.rb +325 -0
  41. data/lib/state_machine/integrations/data_mapper/observer.rb +139 -0
  42. data/lib/state_machine/integrations/sequel.rb +292 -0
  43. data/lib/state_machine/machine.rb +1431 -0
  44. data/lib/state_machine/machine_collection.rb +146 -0
  45. data/lib/state_machine/matcher.rb +123 -0
  46. data/lib/state_machine/matcher_helpers.rb +54 -0
  47. data/lib/state_machine/node_collection.rb +152 -0
  48. data/lib/state_machine/state.rb +249 -0
  49. data/lib/state_machine/state_collection.rb +112 -0
  50. data/lib/state_machine/transition.rb +367 -0
  51. data/tasks/state_machine.rake +1 -0
  52. data/tasks/state_machine.rb +30 -0
  53. data/test/classes/switch.rb +11 -0
  54. data/test/functional/state_machine_test.rb +941 -0
  55. data/test/test_helper.rb +4 -0
  56. data/test/unit/assertions_test.rb +40 -0
  57. data/test/unit/callback_test.rb +455 -0
  58. data/test/unit/condition_proxy_test.rb +328 -0
  59. data/test/unit/eval_helpers_test.rb +129 -0
  60. data/test/unit/event_collection_test.rb +293 -0
  61. data/test/unit/event_test.rb +605 -0
  62. data/test/unit/guard_test.rb +862 -0
  63. data/test/unit/integrations/active_record_test.rb +1001 -0
  64. data/test/unit/integrations/data_mapper_test.rb +694 -0
  65. data/test/unit/integrations/sequel_test.rb +486 -0
  66. data/test/unit/integrations_test.rb +42 -0
  67. data/test/unit/invalid_event_test.rb +7 -0
  68. data/test/unit/invalid_transition_test.rb +7 -0
  69. data/test/unit/machine_collection_test.rb +710 -0
  70. data/test/unit/machine_test.rb +1910 -0
  71. data/test/unit/matcher_helpers_test.rb +37 -0
  72. data/test/unit/matcher_test.rb +155 -0
  73. data/test/unit/node_collection_test.rb +207 -0
  74. data/test/unit/state_collection_test.rb +280 -0
  75. data/test/unit/state_machine_test.rb +31 -0
  76. data/test/unit/state_test.rb +795 -0
  77. data/test/unit/transition_test.rb +1113 -0
  78. metadata +161 -0
@@ -0,0 +1,862 @@
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 GuardWithConflictingFromRequirementsTest < Test::Unit::TestCase
408
+ def test_should_raise_an_exception
409
+ exception = assert_raise(ArgumentError) { StateMachine::Guard.new(:from => :parked, :except_from => :parked) }
410
+ assert_equal 'Conflicting keys: from, except_from', exception.message
411
+ end
412
+ end
413
+
414
+ class GuardWithConflictingToRequirementsTest < Test::Unit::TestCase
415
+ def test_should_raise_an_exception
416
+ exception = assert_raise(ArgumentError) { StateMachine::Guard.new(:to => :idling, :except_to => :idling) }
417
+ assert_equal 'Conflicting keys: to, except_to', exception.message
418
+ end
419
+ end
420
+
421
+ class GuardWithConflictingOnRequirementsTest < Test::Unit::TestCase
422
+ def test_should_raise_an_exception
423
+ exception = assert_raise(ArgumentError) { StateMachine::Guard.new(:on => :ignite, :except_on => :ignite) }
424
+ assert_equal 'Conflicting keys: on, except_on', exception.message
425
+ end
426
+ end
427
+
428
+ class GuardWithDifferentRequirementsTest < Test::Unit::TestCase
429
+ def setup
430
+ @object = Object.new
431
+ @guard = StateMachine::Guard.new(:from => :parked, :to => :idling, :on => :ignite)
432
+ end
433
+
434
+ def test_should_match_empty_query
435
+ assert @guard.matches?(@object)
436
+ end
437
+
438
+ def test_should_match_if_all_requirements_match
439
+ assert @guard.matches?(@object, :from => :parked, :to => :idling, :on => :ignite)
440
+ end
441
+
442
+ def test_should_not_match_if_from_not_included
443
+ assert !@guard.matches?(@object, :from => :idling)
444
+ end
445
+
446
+ def test_should_not_match_if_to_not_included
447
+ assert !@guard.matches?(@object, :to => :parked)
448
+ end
449
+
450
+ def test_should_not_match_if_on_not_included
451
+ assert !@guard.matches?(@object, :on => :park)
452
+ end
453
+
454
+ def test_should_be_nil_if_unmatched
455
+ assert_nil @guard.match(@object, :from => :parked, :to => :idling, :on => :park)
456
+ end
457
+
458
+ def test_should_include_all_known_states
459
+ assert_equal [:parked, :idling], @guard.known_states
460
+ end
461
+
462
+ def test_should_not_duplicate_known_statse
463
+ guard = StateMachine::Guard.new(:except_from => :idling, :to => :idling, :on => :ignite)
464
+ assert_equal [:idling], guard.known_states
465
+ end
466
+ end
467
+
468
+ class GuardWithNilRequirementsTest < Test::Unit::TestCase
469
+ def setup
470
+ @object = Object.new
471
+ @guard = StateMachine::Guard.new(:from => nil, :to => nil)
472
+ end
473
+
474
+ def test_should_match_empty_query
475
+ assert @guard.matches?(@object)
476
+ end
477
+
478
+ def test_should_match_if_all_requirements_match
479
+ assert @guard.matches?(@object, :from => nil, :to => nil)
480
+ end
481
+
482
+ def test_should_not_match_if_from_not_included
483
+ assert !@guard.matches?(@object, :from => :parked)
484
+ end
485
+
486
+ def test_should_not_match_if_to_not_included
487
+ assert !@guard.matches?(@object, :to => :idling)
488
+ end
489
+
490
+ def test_should_include_all_known_states
491
+ assert_equal [nil], @guard.known_states
492
+ end
493
+ end
494
+
495
+ class GuardWithImplicitRequirementTest < Test::Unit::TestCase
496
+ def setup
497
+ @guard = StateMachine::Guard.new(:parked => :idling, :on => :ignite)
498
+ end
499
+
500
+ def test_should_create_an_event_requirement
501
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.event_requirement
502
+ assert_equal [:ignite], @guard.event_requirement.values
503
+ end
504
+
505
+ def test_should_use_a_whitelist_from_matcher
506
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:from]
507
+ end
508
+
509
+ def test_should_use_a_whitelist_to_matcher
510
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:to]
511
+ end
512
+ end
513
+
514
+ class GuardWithMultipleImplicitRequirementsTest < Test::Unit::TestCase
515
+ def setup
516
+ @object = Object.new
517
+ @guard = StateMachine::Guard.new(:parked => :idling, :idling => :first_gear, :on => :ignite)
518
+ end
519
+
520
+ def test_should_create_multiple_state_requirements
521
+ assert_equal 2, @guard.state_requirements.length
522
+ end
523
+
524
+ def test_should_not_match_event_as_state_requirement
525
+ assert !@guard.matches?(@object, :from => :on, :to => :ignite)
526
+ end
527
+
528
+ def test_should_match_if_from_included_in_any
529
+ assert @guard.matches?(@object, :from => :parked)
530
+ assert @guard.matches?(@object, :from => :idling)
531
+ end
532
+
533
+ def test_should_not_match_if_from_not_included_in_any
534
+ assert !@guard.matches?(@object, :from => :first_gear)
535
+ end
536
+
537
+ def test_should_match_if_to_included_in_any
538
+ assert @guard.matches?(@object, :to => :idling)
539
+ assert @guard.matches?(@object, :to => :first_gear)
540
+ end
541
+
542
+ def test_should_not_match_if_to_not_included_in_any
543
+ assert !@guard.matches?(@object, :to => :parked)
544
+ end
545
+
546
+ def test_should_match_if_all_options_match
547
+ assert @guard.matches?(@object, :from => :parked, :to => :idling, :on => :ignite)
548
+ assert @guard.matches?(@object, :from => :idling, :to => :first_gear, :on => :ignite)
549
+ end
550
+
551
+ def test_should_not_match_if_any_options_do_not_match
552
+ assert !@guard.matches?(@object, :from => :parked, :to => :idling, :on => :park)
553
+ assert !@guard.matches?(@object, :from => :parked, :to => :first_gear, :on => :park)
554
+ end
555
+
556
+ def test_should_include_all_known_states
557
+ assert_equal [:first_gear, :idling, :parked], @guard.known_states.sort_by {|state| state.to_s}
558
+ end
559
+
560
+ def test_should_not_duplicate_known_statse
561
+ guard = StateMachine::Guard.new(:parked => :idling, :first_gear => :idling)
562
+ assert_equal [:first_gear, :idling, :parked], guard.known_states.sort_by {|state| state.to_s}
563
+ end
564
+ end
565
+
566
+ class GuardWithImplicitFromRequirementMatcherTest < Test::Unit::TestCase
567
+ def setup
568
+ @matcher = StateMachine::BlacklistMatcher.new(:parked)
569
+ @guard = StateMachine::Guard.new(@matcher => :idling)
570
+ end
571
+
572
+ def test_should_not_convert_from_to_whitelist_matcher
573
+ assert_equal @matcher, @guard.state_requirements.first[:from]
574
+ end
575
+
576
+ def test_should_convert_to_to_whitelist_matcher
577
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:to]
578
+ end
579
+ end
580
+
581
+ class GuardWithImplicitToRequirementMatcherTest < Test::Unit::TestCase
582
+ def setup
583
+ @matcher = StateMachine::BlacklistMatcher.new(:idling)
584
+ @guard = StateMachine::Guard.new(:parked => @matcher)
585
+ end
586
+
587
+ def test_should_convert_from_to_whitelist_matcher
588
+ assert_instance_of StateMachine::WhitelistMatcher, @guard.state_requirements.first[:from]
589
+ end
590
+
591
+ def test_should_not_convert_to_to_whitelist_matcher
592
+ assert_equal @matcher, @guard.state_requirements.first[:to]
593
+ end
594
+ end
595
+
596
+ class GuardWithImplicitAndExplicitRequirementsTest < Test::Unit::TestCase
597
+ def setup
598
+ @guard = StateMachine::Guard.new(:parked => :idling, :from => :parked)
599
+ end
600
+
601
+ def test_should_create_multiple_requirements
602
+ assert_equal 2, @guard.state_requirements.length
603
+ end
604
+
605
+ def test_should_create_implicit_requirements_for_implicit_options
606
+ assert(@guard.state_requirements.any? do |state_requirement|
607
+ state_requirement[:from].values == [:parked] && state_requirement[:to].values == [:idling]
608
+ end)
609
+ end
610
+
611
+ def test_should_create_implicit_requirements_for_explicit_options
612
+ assert(@guard.state_requirements.any? do |state_requirement|
613
+ state_requirement[:from].values == [:from] && state_requirement[:to].values == [:parked]
614
+ end)
615
+ end
616
+ end
617
+
618
+ class GuardWithIfConditionalTest < Test::Unit::TestCase
619
+ def setup
620
+ @object = Object.new
621
+ end
622
+
623
+ def test_should_have_an_if_condition
624
+ guard = StateMachine::Guard.new(:if => lambda {true})
625
+ assert_not_nil guard.if_condition
626
+ end
627
+
628
+ def test_should_match_if_true
629
+ guard = StateMachine::Guard.new(:if => lambda {true})
630
+ assert guard.matches?(@object)
631
+ end
632
+
633
+ def test_should_not_match_if_false
634
+ guard = StateMachine::Guard.new(:if => lambda {false})
635
+ assert !guard.matches?(@object)
636
+ end
637
+
638
+ def test_should_be_nil_if_unmatched
639
+ guard = StateMachine::Guard.new(:if => lambda {false})
640
+ assert_nil guard.match(@object)
641
+ end
642
+ end
643
+
644
+ class GuardWithMultipleIfConditionalsTest < Test::Unit::TestCase
645
+ def setup
646
+ @object = Object.new
647
+ end
648
+
649
+ def test_should_match_if_all_are_true
650
+ guard = StateMachine::Guard.new(:if => [lambda {true}, lambda {true}])
651
+ assert guard.match(@object)
652
+ end
653
+
654
+ def test_should_not_match_if_any_are_false
655
+ guard = StateMachine::Guard.new(:if => [lambda {true}, lambda {false}])
656
+ assert !guard.match(@object)
657
+
658
+ guard = StateMachine::Guard.new(:if => [lambda {false}, lambda {true}])
659
+ assert !guard.match(@object)
660
+ end
661
+ end
662
+
663
+ class GuardWithUnlessConditionalTest < Test::Unit::TestCase
664
+ def setup
665
+ @object = Object.new
666
+ end
667
+
668
+ def test_should_have_an_unless_condition
669
+ guard = StateMachine::Guard.new(:unless => lambda {true})
670
+ assert_not_nil guard.unless_condition
671
+ end
672
+
673
+ def test_should_match_if_false
674
+ guard = StateMachine::Guard.new(:unless => lambda {false})
675
+ assert guard.matches?(@object)
676
+ end
677
+
678
+ def test_should_not_match_if_true
679
+ guard = StateMachine::Guard.new(:unless => lambda {true})
680
+ assert !guard.matches?(@object)
681
+ end
682
+
683
+ def test_should_be_nil_if_unmatched
684
+ guard = StateMachine::Guard.new(:unless => lambda {true})
685
+ assert_nil guard.match(@object)
686
+ end
687
+ end
688
+
689
+ class GuardWithMultipleUnlessConditionalsTest < Test::Unit::TestCase
690
+ def setup
691
+ @object = Object.new
692
+ end
693
+
694
+ def test_should_match_if_all_are_false
695
+ guard = StateMachine::Guard.new(:unless => [lambda {false}, lambda {false}])
696
+ assert guard.match(@object)
697
+ end
698
+
699
+ def test_should_not_match_if_any_are_true
700
+ guard = StateMachine::Guard.new(:unless => [lambda {true}, lambda {false}])
701
+ assert !guard.match(@object)
702
+
703
+ guard = StateMachine::Guard.new(:unless => [lambda {false}, lambda {true}])
704
+ assert !guard.match(@object)
705
+ end
706
+ end
707
+
708
+ class GuardWithConflictingConditionalsTest < Test::Unit::TestCase
709
+ def test_should_match_if_if_is_true_and_unless_is_false
710
+ guard = StateMachine::Guard.new(:if => lambda {true}, :unless => lambda {false})
711
+ assert guard.match(@object)
712
+ end
713
+
714
+ def test_should_not_match_if_if_is_false_and_unless_is_true
715
+ guard = StateMachine::Guard.new(:if => lambda {false}, :unless => lambda {true})
716
+ assert !guard.match(@object)
717
+ end
718
+
719
+ def test_should_not_match_if_if_is_false_and_unless_is_false
720
+ guard = StateMachine::Guard.new(:if => lambda {false}, :unless => lambda {false})
721
+ assert !guard.match(@object)
722
+ end
723
+
724
+ def test_should_not_match_if_if_is_true_and_unless_is_true
725
+ guard = StateMachine::Guard.new(:if => lambda {true}, :unless => lambda {true})
726
+ assert !guard.match(@object)
727
+ end
728
+ end
729
+
730
+ begin
731
+ # Load library
732
+ require 'rubygems'
733
+ require 'graphviz'
734
+
735
+ class GuardDrawingTest < Test::Unit::TestCase
736
+ def setup
737
+ @machine = StateMachine::Machine.new(Class.new)
738
+ states = [:parked, :idling]
739
+
740
+ graph = GraphViz.new('G')
741
+ states.each {|state| graph.add_node(state.to_s)}
742
+
743
+ @guard = StateMachine::Guard.new(:from => :idling, :to => :parked)
744
+ @edges = @guard.draw(graph, :park, states)
745
+ end
746
+
747
+ def test_should_create_edges
748
+ assert_equal 1, @edges.size
749
+ end
750
+
751
+ def test_should_use_from_state_from_start_node
752
+ assert_equal 'idling', @edges.first.instance_variable_get('@xNodeOne')
753
+ end
754
+
755
+ def test_should_use_to_state_for_end_node
756
+ assert_equal 'parked', @edges.first.instance_variable_get('@xNodeTwo')
757
+ end
758
+
759
+ def test_should_use_event_name_as_label
760
+ assert_equal 'park', @edges.first['label']
761
+ end
762
+ end
763
+
764
+ class GuardDrawingWithFromRequirementTest < Test::Unit::TestCase
765
+ def setup
766
+ @machine = StateMachine::Machine.new(Class.new)
767
+ states = [:parked, :idling, :first_gear]
768
+
769
+ graph = GraphViz.new('G')
770
+ states.each {|state| graph.add_node(state.to_s)}
771
+
772
+ @guard = StateMachine::Guard.new(:from => [:idling, :first_gear], :to => :parked)
773
+ @edges = @guard.draw(graph, :park, states)
774
+ end
775
+
776
+ def test_should_generate_edges_for_each_valid_from_state
777
+ [:idling, :first_gear].each_with_index do |from_state, index|
778
+ edge = @edges[index]
779
+ assert_equal from_state.to_s, edge.instance_variable_get('@xNodeOne')
780
+ assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
781
+ end
782
+ end
783
+ end
784
+
785
+ class GuardDrawingWithExceptFromRequirementTest < Test::Unit::TestCase
786
+ def setup
787
+ @machine = StateMachine::Machine.new(Class.new)
788
+ states = [:parked, :idling, :first_gear]
789
+
790
+ graph = GraphViz.new('G')
791
+ states.each {|state| graph.add_node(state.to_s)}
792
+
793
+ @guard = StateMachine::Guard.new(:except_from => :parked, :to => :parked)
794
+ @edges = @guard.draw(graph, :park, states)
795
+ end
796
+
797
+ def test_should_generate_edges_for_each_valid_from_state
798
+ %w(idling first_gear).each_with_index do |from_state, index|
799
+ edge = @edges[index]
800
+ assert_equal from_state, edge.instance_variable_get('@xNodeOne')
801
+ assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
802
+ end
803
+ end
804
+ end
805
+
806
+ class GuardDrawingWithoutFromRequirementTest < Test::Unit::TestCase
807
+ def setup
808
+ @machine = StateMachine::Machine.new(Class.new)
809
+ states = [:parked, :idling, :first_gear]
810
+
811
+ graph = GraphViz.new('G')
812
+ states.each {|state| graph.add_node(state.to_s)}
813
+
814
+ @guard = StateMachine::Guard.new(:to => :parked)
815
+ @edges = @guard.draw(graph, :park, states)
816
+ end
817
+
818
+ def test_should_generate_edges_for_each_valid_from_state
819
+ %w(parked idling first_gear).each_with_index do |from_state, index|
820
+ edge = @edges[index]
821
+ assert_equal from_state, edge.instance_variable_get('@xNodeOne')
822
+ assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
823
+ end
824
+ end
825
+ end
826
+
827
+ class GuardDrawingWithoutToRequirementTest < Test::Unit::TestCase
828
+ def setup
829
+ @machine = StateMachine::Machine.new(Class.new)
830
+
831
+ graph = GraphViz.new('G')
832
+ graph.add_node('parked')
833
+
834
+ @guard = StateMachine::Guard.new(:from => :parked)
835
+ @edges = @guard.draw(graph, :park, [:parked])
836
+ end
837
+
838
+ def test_should_create_loopback_edge
839
+ assert_equal 'parked', @edges.first.instance_variable_get('@xNodeOne')
840
+ assert_equal 'parked', @edges.first.instance_variable_get('@xNodeTwo')
841
+ end
842
+ end
843
+
844
+ class GuardDrawingWithNilStateTest < Test::Unit::TestCase
845
+ def setup
846
+ @machine = StateMachine::Machine.new(Class.new)
847
+
848
+ graph = GraphViz.new('G')
849
+ graph.add_node('parked')
850
+
851
+ @guard = StateMachine::Guard.new(:from => :idling, :to => nil)
852
+ @edges = @guard.draw(graph, :park, [nil, :idling])
853
+ end
854
+
855
+ def test_should_generate_edges_for_each_valid_from_state
856
+ assert_equal 'idling', @edges.first.instance_variable_get('@xNodeOne')
857
+ assert_equal 'nil', @edges.first.instance_variable_get('@xNodeTwo')
858
+ end
859
+ end
860
+ rescue LoadError
861
+ $stderr.puts 'Skipping GraphViz StateMachine::Guard tests. `gem install ruby-graphviz` and try again.'
862
+ end