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,328 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class Validateable
4
+ class << self
5
+ def validate(*args, &block)
6
+ args << block if block_given?
7
+ args
8
+ end
9
+ end
10
+ end
11
+
12
+ class ConditionProxyTest < Test::Unit::TestCase
13
+ def test_should_call_class_with_same_arguments
14
+ options = {}
15
+ condition_proxy = StateMachine::ConditionProxy.new(Validateable, lambda {})
16
+ validation = condition_proxy.validate(:name, options)
17
+
18
+ assert_equal [:name, options], validation
19
+ end
20
+
21
+ def test_should_pass_block_through_to_class
22
+ options = {}
23
+ condition_proxy = StateMachine::ConditionProxy.new(Validateable, lambda {})
24
+
25
+ proxy_block = lambda {}
26
+ validation = condition_proxy.validate(:name, options, &proxy_block)
27
+
28
+ assert_equal [:name, options, proxy_block], validation
29
+ end
30
+
31
+ def test_should_pass_object_into_proxy_condition
32
+ condition_args = []
33
+ condition_proxy = StateMachine::ConditionProxy.new(Validateable, lambda {|*args| condition_args = args})
34
+ options = condition_proxy.validate[0]
35
+
36
+ object = Validateable.new
37
+ options[:if].call(object)
38
+
39
+ assert_equal [object], condition_args
40
+ end
41
+
42
+ def test_should_evaluate_symbol_condition
43
+ klass = Class.new(Validateable) do
44
+ attr_accessor :callback_called
45
+
46
+ def callback
47
+ @callback_called = true
48
+ end
49
+ end
50
+
51
+ condition_proxy = StateMachine::ConditionProxy.new(klass, :callback)
52
+ options = condition_proxy.validate[0]
53
+
54
+ object = klass.new
55
+ options[:if].call(object)
56
+
57
+ assert object.callback_called
58
+ end
59
+
60
+ def test_should_evaluate_string_condition
61
+ klass = Class.new(Validateable) do
62
+ attr_accessor :callback_called
63
+ end
64
+
65
+ condition_proxy = StateMachine::ConditionProxy.new(klass, '@callback_called = true')
66
+ options = condition_proxy.validate[0]
67
+
68
+ object = klass.new
69
+ options[:if].call(object)
70
+
71
+ assert object.callback_called
72
+ end
73
+ end
74
+
75
+ class ConditionProxyWithoutConditionsTest < Test::Unit::TestCase
76
+ def setup
77
+ @proxy_result = nil
78
+ condition_proxy = StateMachine::ConditionProxy.new(Validateable, lambda {@proxy_result})
79
+
80
+ @object = Validateable.new
81
+ @options = condition_proxy.validate[0]
82
+ end
83
+
84
+ def test_should_have_options_configuration
85
+ assert_instance_of Hash, @options
86
+ end
87
+
88
+ def test_should_have_if_option
89
+ assert_not_nil @options[:if]
90
+ end
91
+
92
+ def test_should_be_false_if_proxy_condition_is_false
93
+ @proxy_result = false
94
+ assert !@options[:if].call(@object)
95
+ end
96
+
97
+ def test_should_be_true_if_proxy_condition_is_true
98
+ @proxy_result = true
99
+ assert @options[:if].call(@object)
100
+ end
101
+
102
+ def test_should_be_true_if_proxy_condition_is_not_true
103
+ @proxy_result = 1
104
+ assert @options[:if].call(@object)
105
+ end
106
+ end
107
+
108
+ class ConditionProxyWithIfConditionTest < Test::Unit::TestCase
109
+ def setup
110
+ @proxy_result = nil
111
+ condition_proxy = StateMachine::ConditionProxy.new(Validateable, lambda {@proxy_result})
112
+
113
+ @object = Validateable.new
114
+
115
+ @condition_result = nil
116
+ @options = condition_proxy.validate(:if => lambda {@condition_result})[0]
117
+ end
118
+
119
+ def test_should_have_if_option
120
+ assert_not_nil @options[:if]
121
+ end
122
+
123
+ def test_should_be_false_if_proxy_condition_is_false
124
+ @proxy_result = false
125
+ assert !@options[:if].call(@object)
126
+ end
127
+
128
+ def test_should_be_false_if_original_condition_is_false
129
+ @condition_result = false
130
+ assert !@options[:if].call(@object)
131
+ end
132
+
133
+ def test_should_be_true_if_proxy_and_original_condition_are_true
134
+ @proxy_result = true
135
+ @condition_result = true
136
+ assert @options[:if].call(@object)
137
+ end
138
+
139
+ def test_should_evaluate_symbol_condition
140
+ klass = Class.new(Validateable) do
141
+ attr_accessor :callback
142
+ end
143
+
144
+ condition_proxy = StateMachine::ConditionProxy.new(klass, lambda {true})
145
+ options = condition_proxy.validate(:if => :callback)[0]
146
+
147
+ object = klass.new
148
+ object.callback = false
149
+ assert !options[:if].call(object)
150
+
151
+ object.callback = true
152
+ assert options[:if].call(object)
153
+ end
154
+
155
+ def test_should_evaluate_string_condition
156
+ klass = Class.new(Validateable) do
157
+ attr_accessor :callback
158
+ end
159
+
160
+ condition_proxy = StateMachine::ConditionProxy.new(klass, lambda {true})
161
+ options = condition_proxy.validate(:if => '@callback')[0]
162
+
163
+ object = klass.new
164
+ object.callback = false
165
+ assert !options[:if].call(object)
166
+
167
+ object.callback = true
168
+ assert options[:if].call(object)
169
+ end
170
+ end
171
+
172
+ class ConditionProxyWithMultipleIfConditionsTest < Test::Unit::TestCase
173
+ def setup
174
+ condition_proxy = StateMachine::ConditionProxy.new(Validateable, lambda {true})
175
+
176
+ @object = Validateable.new
177
+
178
+ @first_condition_result = nil
179
+ @second_condition_result = nil
180
+ @options = condition_proxy.validate(:if => [lambda {@first_condition_result}, lambda {@second_condition_result}])[0]
181
+ end
182
+
183
+ def test_should_be_true_if_all_conditions_are_true
184
+ @first_condition_result = true
185
+ @second_condition_result = true
186
+ assert @options[:if].call(@object)
187
+ end
188
+
189
+ def test_should_be_false_if_any_condition_is_false
190
+ @first_condition_result = true
191
+ @second_condition_result = false
192
+ assert !@options[:if].call(@object)
193
+
194
+ @first_condition_result = false
195
+ @second_condition_result = true
196
+ assert !@options[:if].call(@object)
197
+ end
198
+ end
199
+
200
+ class ConditionProxyWithUnlessConditionTest < Test::Unit::TestCase
201
+ def setup
202
+ @proxy_result = nil
203
+ condition_proxy = StateMachine::ConditionProxy.new(Validateable, lambda {@proxy_result})
204
+
205
+ @object = Validateable.new
206
+
207
+ @condition_result = nil
208
+ @options = condition_proxy.validate(:unless => lambda {@condition_result})[0]
209
+ end
210
+
211
+ def test_should_have_if_option
212
+ assert_not_nil @options[:if]
213
+ end
214
+
215
+ def test_should_be_false_if_proxy_condition_is_false
216
+ @proxy_result = false
217
+ assert !@options[:if].call(@object)
218
+ end
219
+
220
+ def test_should_be_false_if_original_condition_is_true
221
+ @condition_result = true
222
+ assert !@options[:if].call(@object)
223
+ end
224
+
225
+ def test_should_be_true_if_proxy_is_true_and_original_condition_is_false
226
+ @proxy_result = true
227
+ @condition_result = false
228
+ assert @options[:if].call(@object)
229
+ end
230
+
231
+ def test_should_evaluate_symbol_condition
232
+ klass = Class.new(Validateable) do
233
+ attr_accessor :callback
234
+ end
235
+
236
+ condition_proxy = StateMachine::ConditionProxy.new(klass, lambda {true})
237
+ options = condition_proxy.validate(:unless => :callback)[0]
238
+
239
+ object = klass.new
240
+ object.callback = true
241
+ assert !options[:if].call(object)
242
+
243
+ object.callback = false
244
+ assert options[:if].call(object)
245
+ end
246
+
247
+ def test_should_evaluate_string_condition
248
+ klass = Class.new(Validateable) do
249
+ attr_accessor :callback
250
+ end
251
+
252
+ condition_proxy = StateMachine::ConditionProxy.new(klass, lambda {true})
253
+ options = condition_proxy.validate(:unless => '@callback')[0]
254
+
255
+ object = klass.new
256
+ object.callback = true
257
+ assert !options[:if].call(object)
258
+
259
+ object.callback = false
260
+ assert options[:if].call(object)
261
+ end
262
+ end
263
+
264
+ class ConditionProxyWithMultipleUnlessConditionsTest < Test::Unit::TestCase
265
+ def setup
266
+ condition_proxy = StateMachine::ConditionProxy.new(Validateable, lambda {true})
267
+
268
+ @object = Validateable.new
269
+
270
+ @first_condition_result = nil
271
+ @second_condition_result = nil
272
+ @options = condition_proxy.validate(:unless => [lambda {@first_condition_result}, lambda {@second_condition_result}])[0]
273
+ end
274
+
275
+ def test_should_be_true_if_all_conditions_are_false
276
+ @first_condition_result = false
277
+ @second_condition_result = false
278
+ assert @options[:if].call(@object)
279
+ end
280
+
281
+ def test_should_be_false_if_any_condition_is_true
282
+ @first_condition_result = true
283
+ @second_condition_result = false
284
+ assert !@options[:if].call(@object)
285
+
286
+ @first_condition_result = false
287
+ @second_condition_result = true
288
+ assert !@options[:if].call(@object)
289
+ end
290
+ end
291
+
292
+ class ConditionProxyWithIfAndUnlessConditionsTest < Test::Unit::TestCase
293
+ def setup
294
+ condition_proxy = StateMachine::ConditionProxy.new(Validateable, lambda {true})
295
+
296
+ @object = Validateable.new
297
+
298
+ @if_condition_result = nil
299
+ @unless_condition_result = nil
300
+ @options = condition_proxy.validate(:if => lambda {@if_condition_result}, :unless => lambda {@unless_condition_result})[0]
301
+ end
302
+
303
+ def test_should_be_false_if_if_condition_is_false
304
+ @if_condition_result = false
305
+ @unless_condition_result = false
306
+ assert !@options[:if].call(@object)
307
+
308
+ @if_condition_result = false
309
+ @unless_condition_result = true
310
+ assert !@options[:if].call(@object)
311
+ end
312
+
313
+ def test_should_be_false_if_unless_condition_is_true
314
+ @if_condition_result = false
315
+ @unless_condition_result = true
316
+ assert !@options[:if].call(@object)
317
+
318
+ @if_condition_result = true
319
+ @unless_condition_result = true
320
+ assert !@options[:if].call(@object)
321
+ end
322
+
323
+ def test_should_be_true_if_if_condition_is_true_and_unless_condition_is_false
324
+ @if_condition_result = true
325
+ @unless_condition_result = false
326
+ assert @options[:if].call(@object)
327
+ end
328
+ end
@@ -0,0 +1,129 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
2
+
3
+ class EvalHelpersTest < Test::Unit::TestCase
4
+ include StateMachine::EvalHelpers
5
+
6
+ def setup
7
+ @object = Object.new
8
+ end
9
+
10
+ def test_should_raise_exception_if_method_is_not_symbol_string_or_proc
11
+ exception = assert_raise(ArgumentError) { evaluate_method(@object, 1) }
12
+ assert_match /Methods must/, exception.message
13
+ end
14
+ end
15
+
16
+ class EvalHelpersSymbolTest < Test::Unit::TestCase
17
+ include StateMachine::EvalHelpers
18
+
19
+ def setup
20
+ class << (@object = Object.new)
21
+ def callback
22
+ true
23
+ end
24
+ end
25
+ end
26
+
27
+ def test_should_call_method_on_object_with_no_arguments
28
+ assert evaluate_method(@object, :callback, 1, 2, 3)
29
+ end
30
+ end
31
+
32
+ class EvalHelpersSymbolWithArgumentsTest < Test::Unit::TestCase
33
+ include StateMachine::EvalHelpers
34
+
35
+ def setup
36
+ class << (@object = Object.new)
37
+ def callback(*args)
38
+ args
39
+ end
40
+ end
41
+ end
42
+
43
+ def test_should_call_method_with_all_arguments
44
+ assert_equal [1, 2, 3], evaluate_method(@object, :callback, 1, 2, 3)
45
+ end
46
+ end
47
+
48
+ class EvalHelpersSymbolTaintedMethodTest < Test::Unit::TestCase
49
+ include StateMachine::EvalHelpers
50
+
51
+ def setup
52
+ class << (@object = Object.new)
53
+ def callback
54
+ true
55
+ end
56
+
57
+ taint
58
+ end
59
+ end
60
+
61
+ def test_should_not_raise_security_error
62
+ assert_nothing_raised { evaluate_method(@object, :callback, 1, 2, 3) }
63
+ end
64
+ end
65
+
66
+ class EvalHelpersStringTest < Test::Unit::TestCase
67
+ include StateMachine::EvalHelpers
68
+
69
+ def setup
70
+ @object = Object.new
71
+ end
72
+
73
+ def test_should_evaluate_string
74
+ assert_equal 1, evaluate_method(@object, '1')
75
+ end
76
+
77
+ def test_should_evaluate_string_within_object_context
78
+ @object.instance_variable_set('@value', 1)
79
+ assert_equal 1, evaluate_method(@object, '@value')
80
+ end
81
+
82
+ def test_should_ignore_additional_arguments
83
+ assert_equal 1, evaluate_method(@object, '1', 2, 3, 4)
84
+ end
85
+ end
86
+
87
+ class EvalHelpersProcTest < Test::Unit::TestCase
88
+ include StateMachine::EvalHelpers
89
+
90
+ def setup
91
+ @object = Object.new
92
+ @proc = lambda {|obj| obj}
93
+ end
94
+
95
+ def test_should_call_proc_with_object_as_argument
96
+ assert_equal @object, evaluate_method(@object, @proc, 1, 2, 3)
97
+ end
98
+ end
99
+
100
+ class EvalHelpersProcWithoutArgumentsTest < Test::Unit::TestCase
101
+ include StateMachine::EvalHelpers
102
+
103
+ def setup
104
+ @object = Object.new
105
+ @proc = lambda {|*args| args}
106
+ class << @proc
107
+ def arity
108
+ 0
109
+ end
110
+ end
111
+ end
112
+
113
+ def test_should_call_proc_with_no_arguments
114
+ assert_equal [], evaluate_method(@object, @proc, 1, 2, 3)
115
+ end
116
+ end
117
+
118
+ class EvalHelpersProcWithArgumentsTest < Test::Unit::TestCase
119
+ include StateMachine::EvalHelpers
120
+
121
+ def setup
122
+ @object = Object.new
123
+ @proc = lambda {|*args| args}
124
+ end
125
+
126
+ def test_should_call_method_with_all_arguments
127
+ assert_equal [@object, 1, 2, 3], evaluate_method(@object, @proc, 1, 2, 3)
128
+ end
129
+ end