pluginaweek-state_machine 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
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