state_machine 1.0.1 → 1.0.2
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.
- data/.gitignore +11 -0
- data/.travis.yml +16 -0
- data/.yardopts +5 -0
- data/Appraisals +260 -0
- data/CHANGELOG.rdoc +15 -0
- data/Gemfile +3 -0
- data/README.rdoc +156 -29
- data/Rakefile +31 -57
- data/gemfiles/active_model-3.0.0.gemfile +7 -0
- data/gemfiles/active_model-3.0.0.gemfile.lock +32 -0
- data/gemfiles/active_model-3.0.5.gemfile +7 -0
- data/gemfiles/active_model-3.0.5.gemfile.lock +32 -0
- data/gemfiles/active_record-2.0.0.gemfile +8 -0
- data/gemfiles/active_record-2.0.0.gemfile.lock +30 -0
- data/gemfiles/active_record-2.0.5.gemfile +8 -0
- data/gemfiles/active_record-2.0.5.gemfile.lock +30 -0
- data/gemfiles/active_record-2.1.0.gemfile +8 -0
- data/gemfiles/active_record-2.1.0.gemfile.lock +30 -0
- data/gemfiles/active_record-2.1.2.gemfile +8 -0
- data/gemfiles/active_record-2.1.2.gemfile.lock +30 -0
- data/gemfiles/active_record-2.2.3.gemfile +8 -0
- data/gemfiles/active_record-2.2.3.gemfile.lock +30 -0
- data/gemfiles/active_record-2.3.12.gemfile +8 -0
- data/gemfiles/active_record-2.3.12.gemfile.lock +30 -0
- data/gemfiles/active_record-3.0.0.gemfile +8 -0
- data/gemfiles/active_record-3.0.0.gemfile.lock +44 -0
- data/gemfiles/active_record-3.0.5.gemfile +8 -0
- data/gemfiles/active_record-3.0.5.gemfile.lock +43 -0
- data/gemfiles/data_mapper-0.10.2.gemfile +12 -0
- data/gemfiles/data_mapper-0.10.2.gemfile.lock +45 -0
- data/gemfiles/data_mapper-0.9.11.gemfile +12 -0
- data/gemfiles/data_mapper-0.9.11.gemfile.lock +47 -0
- data/gemfiles/data_mapper-0.9.4.gemfile +12 -0
- data/gemfiles/data_mapper-0.9.4.gemfile.lock +61 -0
- data/gemfiles/data_mapper-0.9.7.gemfile +12 -0
- data/gemfiles/data_mapper-0.9.7.gemfile.lock +57 -0
- data/gemfiles/data_mapper-1.0.0.gemfile +12 -0
- data/gemfiles/data_mapper-1.0.0.gemfile.lock +53 -0
- data/gemfiles/data_mapper-1.0.1.gemfile +12 -0
- data/gemfiles/data_mapper-1.0.1.gemfile.lock +53 -0
- data/gemfiles/data_mapper-1.0.2.gemfile +12 -0
- data/gemfiles/data_mapper-1.0.2.gemfile.lock +53 -0
- data/gemfiles/data_mapper-1.1.0.gemfile +12 -0
- data/gemfiles/data_mapper-1.1.0.gemfile.lock +51 -0
- data/gemfiles/default.gemfile +7 -0
- data/gemfiles/default.gemfile.lock +24 -0
- data/gemfiles/mongo_mapper-0.5.5.gemfile +8 -0
- data/gemfiles/mongo_mapper-0.5.5.gemfile.lock +33 -0
- data/gemfiles/mongo_mapper-0.5.8.gemfile +8 -0
- data/gemfiles/mongo_mapper-0.5.8.gemfile.lock +33 -0
- data/gemfiles/mongo_mapper-0.6.0.gemfile +8 -0
- data/gemfiles/mongo_mapper-0.6.0.gemfile.lock +33 -0
- data/gemfiles/mongo_mapper-0.6.10.gemfile +8 -0
- data/gemfiles/mongo_mapper-0.6.10.gemfile.lock +33 -0
- data/gemfiles/mongo_mapper-0.7.0.gemfile +8 -0
- data/gemfiles/mongo_mapper-0.7.0.gemfile.lock +33 -0
- data/gemfiles/mongo_mapper-0.7.5.gemfile +8 -0
- data/gemfiles/mongo_mapper-0.7.5.gemfile.lock +36 -0
- data/gemfiles/mongo_mapper-0.8.0.gemfile +10 -0
- data/gemfiles/mongo_mapper-0.8.0.gemfile.lock +40 -0
- data/gemfiles/mongo_mapper-0.8.3.gemfile +10 -0
- data/gemfiles/mongo_mapper-0.8.3.gemfile.lock +40 -0
- data/gemfiles/mongo_mapper-0.8.4.gemfile +8 -0
- data/gemfiles/mongo_mapper-0.8.4.gemfile.lock +38 -0
- data/gemfiles/mongo_mapper-0.8.6.gemfile +8 -0
- data/gemfiles/mongo_mapper-0.8.6.gemfile.lock +38 -0
- data/gemfiles/mongo_mapper-0.9.0.gemfile +7 -0
- data/gemfiles/mongo_mapper-0.9.0.gemfile.lock +41 -0
- data/gemfiles/mongoid-2.0.0.gemfile +7 -0
- data/gemfiles/mongoid-2.0.0.gemfile.lock +42 -0
- data/gemfiles/mongoid-2.1.4.gemfile +7 -0
- data/gemfiles/mongoid-2.1.4.gemfile.lock +40 -0
- data/gemfiles/sequel-2.11.0.gemfile +8 -0
- data/gemfiles/sequel-2.11.0.gemfile.lock +28 -0
- data/gemfiles/sequel-2.12.0.gemfile +8 -0
- data/gemfiles/sequel-2.12.0.gemfile.lock +28 -0
- data/gemfiles/sequel-2.8.0.gemfile +8 -0
- data/gemfiles/sequel-2.8.0.gemfile.lock +28 -0
- data/gemfiles/sequel-3.0.0.gemfile +8 -0
- data/gemfiles/sequel-3.0.0.gemfile.lock +28 -0
- data/gemfiles/sequel-3.13.0.gemfile +8 -0
- data/gemfiles/sequel-3.13.0.gemfile.lock +28 -0
- data/gemfiles/sequel-3.14.0.gemfile +8 -0
- data/gemfiles/sequel-3.14.0.gemfile.lock +28 -0
- data/gemfiles/sequel-3.23.0.gemfile +8 -0
- data/gemfiles/sequel-3.23.0.gemfile.lock +28 -0
- data/gemfiles/sequel-3.24.0.gemfile +8 -0
- data/gemfiles/sequel-3.24.0.gemfile.lock +28 -0
- data/lib/state_machine/event.rb +13 -90
- data/lib/state_machine/helper_module.rb +17 -0
- data/lib/state_machine/integrations/active_model.rb +35 -0
- data/lib/state_machine/integrations/active_record.rb +41 -2
- data/lib/state_machine/integrations/data_mapper.rb +17 -2
- data/lib/state_machine/integrations/mongo_mapper.rb +34 -7
- data/lib/state_machine/integrations/mongoid.rb +34 -26
- data/lib/state_machine/integrations/mongoid/versions.rb +29 -3
- data/lib/state_machine/integrations/sequel.rb +22 -72
- data/lib/state_machine/integrations/sequel/versions.rb +87 -6
- data/lib/state_machine/machine.rb +279 -19
- data/lib/state_machine/state.rb +2 -2
- data/lib/state_machine/state_context.rb +133 -0
- data/lib/state_machine/version.rb +3 -0
- data/state_machine.gemspec +22 -0
- data/test/test_helper.rb +1 -3
- data/test/unit/branch_test.rb +1 -3
- data/test/unit/event_collection_test.rb +3 -3
- data/test/unit/event_test.rb +1 -3
- data/test/unit/helper_module_test.rb +17 -0
- data/test/unit/integrations/active_model_test.rb +0 -4
- data/test/unit/integrations/active_record_test.rb +50 -9
- data/test/unit/integrations/data_mapper_test.rb +267 -253
- data/test/unit/integrations/mongo_mapper_test.rb +47 -15
- data/test/unit/integrations/mongoid_test.rb +50 -8
- data/test/unit/integrations/sequel_test.rb +10 -6
- data/test/unit/machine_test.rb +206 -25
- data/test/unit/state_context_test.rb +421 -0
- data/test/unit/state_test.rb +20 -3
- metadata +303 -128
- data/lib/state_machine/condition_proxy.rb +0 -94
- data/test/unit/condition_proxy_test.rb +0 -328
|
@@ -0,0 +1,421 @@
|
|
|
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 StateContextTest < Test::Unit::TestCase
|
|
13
|
+
def setup
|
|
14
|
+
@klass = Class.new(Validateable)
|
|
15
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
|
16
|
+
@state = @machine.state :parked
|
|
17
|
+
|
|
18
|
+
@state_context = StateMachine::StateContext.new(@state)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_should_have_a_machine
|
|
22
|
+
assert_equal @machine, @state_context.machine
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_should_have_a_state
|
|
26
|
+
assert_equal @state, @state_context.state
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class StateContextTransitionTest < Test::Unit::TestCase
|
|
31
|
+
def setup
|
|
32
|
+
@klass = Class.new
|
|
33
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
|
34
|
+
@state = @machine.state :parked
|
|
35
|
+
|
|
36
|
+
@state_context = StateMachine::StateContext.new(@state)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_should_not_allow_except_to
|
|
40
|
+
exception = assert_raise(ArgumentError) { @state_context.transition(:except_to => :idling) }
|
|
41
|
+
assert_equal 'Invalid key(s): except_to', exception.message
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_should_not_allow_from
|
|
45
|
+
exception = assert_raise(ArgumentError) { @state_context.transition(:from => :idling) }
|
|
46
|
+
assert_equal 'Invalid key(s): from', exception.message
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def test_should_not_allow_except_from
|
|
50
|
+
exception = assert_raise(ArgumentError) { @state_context.transition(:except_from => :idling) }
|
|
51
|
+
assert_equal 'Invalid key(s): except_from', exception.message
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_should_not_allow_implicit_transitions
|
|
55
|
+
exception = assert_raise(ArgumentError) { @state_context.transition(:parked => :idling) }
|
|
56
|
+
assert_equal 'Invalid key(s): parked', exception.message
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_should_not_allow_except_on
|
|
60
|
+
exception = assert_raise(ArgumentError) { @state_context.transition(:except_on => :park) }
|
|
61
|
+
assert_equal 'Invalid key(s): except_on', exception.message
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_should_require_on_event
|
|
65
|
+
exception = assert_raise(ArgumentError) { @state_context.transition(:to => :idling) }
|
|
66
|
+
assert_equal 'Must specify :to state and :on event', exception.message
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_should_require_to_state
|
|
70
|
+
exception = assert_raise(ArgumentError) { @state_context.transition(:on => :ignite) }
|
|
71
|
+
assert_equal 'Must specify :to state and :on event', exception.message
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_should_automatically_set_from_option
|
|
75
|
+
branch = @state_context.transition(:to => :idling, :on => :ignite)
|
|
76
|
+
assert_instance_of StateMachine::Branch, branch
|
|
77
|
+
|
|
78
|
+
state_requirements = branch.state_requirements
|
|
79
|
+
assert_equal 1, state_requirements.length
|
|
80
|
+
|
|
81
|
+
from_requirement = state_requirements[0][:from]
|
|
82
|
+
assert_instance_of StateMachine::WhitelistMatcher, from_requirement
|
|
83
|
+
assert_equal [:parked], from_requirement.values
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def test_should_allow_if_condition
|
|
87
|
+
assert_nothing_raised {@state_context.transition(:to => :idling, :on => :park, :if => :seatbelt_on?)}
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_should_allow_unless_condition
|
|
91
|
+
assert_nothing_raised {@state_context.transition(:to => :idling, :on => :park, :unless => :seatbelt_off?)}
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_should_include_all_transition_states_in_machine_states
|
|
95
|
+
@state_context.transition(:to => :idling, :on => :ignite)
|
|
96
|
+
|
|
97
|
+
assert_equal [:parked, :idling], @machine.states.map {|state| state.name}
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def test_should_include_all_transition_events_in_machine_events
|
|
101
|
+
@state_context.transition(:to => :idling, :on => :ignite)
|
|
102
|
+
|
|
103
|
+
assert_equal [:ignite], @machine.events.map {|event| event.name}
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_should_allow_multiple_events
|
|
107
|
+
@state_context.transition(:to => :idling, :on => [:ignite, :shift_up])
|
|
108
|
+
|
|
109
|
+
assert_equal [:ignite, :shift_up], @machine.events.map {|event| event.name}
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
class StateContextWithMatchingTransitionTest < Test::Unit::TestCase
|
|
114
|
+
def setup
|
|
115
|
+
@klass = Class.new
|
|
116
|
+
@machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
|
117
|
+
@state = @machine.state :parked
|
|
118
|
+
|
|
119
|
+
@state_context = StateMachine::StateContext.new(@state)
|
|
120
|
+
@state_context.transition(:to => :idling, :on => :ignite)
|
|
121
|
+
|
|
122
|
+
@event = @machine.event(:ignite)
|
|
123
|
+
@object = @klass.new
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def test_should_be_able_to_fire
|
|
127
|
+
assert @event.can_fire?(@object)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def test_should_have_a_transition
|
|
131
|
+
transition = @event.transition_for(@object)
|
|
132
|
+
assert_not_nil transition
|
|
133
|
+
assert_equal 'parked', transition.from
|
|
134
|
+
assert_equal 'idling', transition.to
|
|
135
|
+
assert_equal :ignite, transition.event
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
class StateContextProxyTest < Test::Unit::TestCase
|
|
140
|
+
def setup
|
|
141
|
+
@klass = Class.new(Validateable)
|
|
142
|
+
machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
|
143
|
+
state = machine.state :parked
|
|
144
|
+
|
|
145
|
+
@state_context = StateMachine::StateContext.new(state)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def test_should_call_class_with_same_arguments
|
|
149
|
+
options = {}
|
|
150
|
+
validation = @state_context.validate(:name, options)
|
|
151
|
+
|
|
152
|
+
assert_equal [:name, options], validation
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def test_should_pass_block_through_to_class
|
|
156
|
+
options = {}
|
|
157
|
+
proxy_block = lambda {}
|
|
158
|
+
validation = @state_context.validate(:name, options, &proxy_block)
|
|
159
|
+
|
|
160
|
+
assert_equal [:name, options, proxy_block], validation
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
class StateContextProxyWithoutConditionsTest < Test::Unit::TestCase
|
|
165
|
+
def setup
|
|
166
|
+
@klass = Class.new(Validateable)
|
|
167
|
+
machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
|
168
|
+
state = machine.state :parked
|
|
169
|
+
|
|
170
|
+
@state_context = StateMachine::StateContext.new(state)
|
|
171
|
+
@object = @klass.new
|
|
172
|
+
|
|
173
|
+
@options = @state_context.validate[0]
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def test_should_have_options_configuration
|
|
177
|
+
assert_instance_of Hash, @options
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def test_should_have_if_option
|
|
181
|
+
assert_not_nil @options[:if]
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def test_should_be_false_if_state_is_different
|
|
185
|
+
@object.state = nil
|
|
186
|
+
assert !@options[:if].call(@object)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def test_should_be_true_if_state_matches
|
|
190
|
+
assert @options[:if].call(@object)
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
class StateContextProxyWithIfConditionTest < Test::Unit::TestCase
|
|
195
|
+
def setup
|
|
196
|
+
@klass = Class.new(Validateable)
|
|
197
|
+
machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
|
198
|
+
state = machine.state :parked
|
|
199
|
+
|
|
200
|
+
@state_context = StateMachine::StateContext.new(state)
|
|
201
|
+
@object = @klass.new
|
|
202
|
+
|
|
203
|
+
@condition_result = nil
|
|
204
|
+
@options = @state_context.validate(:if => lambda {@condition_result})[0]
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def test_should_have_if_option
|
|
208
|
+
assert_not_nil @options[:if]
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def test_should_be_false_if_state_is_different
|
|
212
|
+
@object.state = nil
|
|
213
|
+
assert !@options[:if].call(@object)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def test_should_be_false_if_original_condition_is_false
|
|
217
|
+
@condition_result = false
|
|
218
|
+
assert !@options[:if].call(@object)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def test_should_be_true_if_state_matches_and_original_condition_is_true
|
|
222
|
+
@condition_result = true
|
|
223
|
+
assert @options[:if].call(@object)
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def test_should_evaluate_symbol_condition
|
|
227
|
+
@klass.class_eval do
|
|
228
|
+
attr_accessor :callback
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
options = @state_context.validate(:if => :callback)[0]
|
|
232
|
+
|
|
233
|
+
object = @klass.new
|
|
234
|
+
object.callback = false
|
|
235
|
+
assert !options[:if].call(object)
|
|
236
|
+
|
|
237
|
+
object.callback = true
|
|
238
|
+
assert options[:if].call(object)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def test_should_evaluate_string_condition
|
|
242
|
+
@klass.class_eval do
|
|
243
|
+
attr_accessor :callback
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
options = @state_context.validate(:if => '@callback')[0]
|
|
247
|
+
|
|
248
|
+
object = @klass.new
|
|
249
|
+
object.callback = false
|
|
250
|
+
assert !options[:if].call(object)
|
|
251
|
+
|
|
252
|
+
object.callback = true
|
|
253
|
+
assert options[:if].call(object)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
class StateContextProxyWithMultipleIfConditionsTest < Test::Unit::TestCase
|
|
258
|
+
def setup
|
|
259
|
+
@klass = Class.new(Validateable)
|
|
260
|
+
machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
|
261
|
+
state = machine.state :parked
|
|
262
|
+
|
|
263
|
+
@state_context = StateMachine::StateContext.new(state)
|
|
264
|
+
@object = @klass.new
|
|
265
|
+
|
|
266
|
+
@first_condition_result = nil
|
|
267
|
+
@second_condition_result = nil
|
|
268
|
+
@options = @state_context.validate(:if => [lambda {@first_condition_result}, lambda {@second_condition_result}])[0]
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def test_should_be_true_if_all_conditions_are_true
|
|
272
|
+
@first_condition_result = true
|
|
273
|
+
@second_condition_result = true
|
|
274
|
+
assert @options[:if].call(@object)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def test_should_be_false_if_any_condition_is_false
|
|
278
|
+
@first_condition_result = true
|
|
279
|
+
@second_condition_result = false
|
|
280
|
+
assert !@options[:if].call(@object)
|
|
281
|
+
|
|
282
|
+
@first_condition_result = false
|
|
283
|
+
@second_condition_result = true
|
|
284
|
+
assert !@options[:if].call(@object)
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
class StateContextProxyWithUnlessConditionTest < Test::Unit::TestCase
|
|
289
|
+
def setup
|
|
290
|
+
@klass = Class.new(Validateable)
|
|
291
|
+
machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
|
292
|
+
state = machine.state :parked
|
|
293
|
+
|
|
294
|
+
@state_context = StateMachine::StateContext.new(state)
|
|
295
|
+
@object = @klass.new
|
|
296
|
+
|
|
297
|
+
@condition_result = nil
|
|
298
|
+
@options = @state_context.validate(:unless => lambda {@condition_result})[0]
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def test_should_have_if_option
|
|
302
|
+
assert_not_nil @options[:if]
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def test_should_be_false_if_state_is_different
|
|
306
|
+
@object.state = nil
|
|
307
|
+
assert !@options[:if].call(@object)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def test_should_be_false_if_original_condition_is_true
|
|
311
|
+
@condition_result = true
|
|
312
|
+
assert !@options[:if].call(@object)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def test_should_be_true_if_state_matches_and_original_condition_is_false
|
|
316
|
+
@condition_result = false
|
|
317
|
+
assert @options[:if].call(@object)
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def test_should_evaluate_symbol_condition
|
|
321
|
+
@klass.class_eval do
|
|
322
|
+
attr_accessor :callback
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
options = @state_context.validate(:unless => :callback)[0]
|
|
326
|
+
|
|
327
|
+
object = @klass.new
|
|
328
|
+
object.callback = true
|
|
329
|
+
assert !options[:if].call(object)
|
|
330
|
+
|
|
331
|
+
object.callback = false
|
|
332
|
+
assert options[:if].call(object)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def test_should_evaluate_string_condition
|
|
336
|
+
@klass.class_eval do
|
|
337
|
+
attr_accessor :callback
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
options = @state_context.validate(:unless => '@callback')[0]
|
|
341
|
+
|
|
342
|
+
object = @klass.new
|
|
343
|
+
object.callback = true
|
|
344
|
+
assert !options[:if].call(object)
|
|
345
|
+
|
|
346
|
+
object.callback = false
|
|
347
|
+
assert options[:if].call(object)
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
class StateContextProxyWithMultipleUnlessConditionsTest < Test::Unit::TestCase
|
|
352
|
+
def setup
|
|
353
|
+
@klass = Class.new(Validateable)
|
|
354
|
+
machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
|
355
|
+
state = machine.state :parked
|
|
356
|
+
|
|
357
|
+
@state_context = StateMachine::StateContext.new(state)
|
|
358
|
+
@object = @klass.new
|
|
359
|
+
|
|
360
|
+
@first_condition_result = nil
|
|
361
|
+
@second_condition_result = nil
|
|
362
|
+
@options = @state_context.validate(:unless => [lambda {@first_condition_result}, lambda {@second_condition_result}])[0]
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
def test_should_be_true_if_all_conditions_are_false
|
|
366
|
+
@first_condition_result = false
|
|
367
|
+
@second_condition_result = false
|
|
368
|
+
assert @options[:if].call(@object)
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def test_should_be_false_if_any_condition_is_true
|
|
372
|
+
@first_condition_result = true
|
|
373
|
+
@second_condition_result = false
|
|
374
|
+
assert !@options[:if].call(@object)
|
|
375
|
+
|
|
376
|
+
@first_condition_result = false
|
|
377
|
+
@second_condition_result = true
|
|
378
|
+
assert !@options[:if].call(@object)
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
class StateContextProxyWithIfAndUnlessConditionsTest < Test::Unit::TestCase
|
|
383
|
+
def setup
|
|
384
|
+
@klass = Class.new(Validateable)
|
|
385
|
+
machine = StateMachine::Machine.new(@klass, :initial => :parked)
|
|
386
|
+
state = machine.state :parked
|
|
387
|
+
|
|
388
|
+
@state_context = StateMachine::StateContext.new(state)
|
|
389
|
+
@object = @klass.new
|
|
390
|
+
|
|
391
|
+
@if_condition_result = nil
|
|
392
|
+
@unless_condition_result = nil
|
|
393
|
+
@options = @state_context.validate(:if => lambda {@if_condition_result}, :unless => lambda {@unless_condition_result})[0]
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def test_should_be_false_if_if_condition_is_false
|
|
397
|
+
@if_condition_result = false
|
|
398
|
+
@unless_condition_result = false
|
|
399
|
+
assert !@options[:if].call(@object)
|
|
400
|
+
|
|
401
|
+
@if_condition_result = false
|
|
402
|
+
@unless_condition_result = true
|
|
403
|
+
assert !@options[:if].call(@object)
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
def test_should_be_false_if_unless_condition_is_true
|
|
407
|
+
@if_condition_result = false
|
|
408
|
+
@unless_condition_result = true
|
|
409
|
+
assert !@options[:if].call(@object)
|
|
410
|
+
|
|
411
|
+
@if_condition_result = true
|
|
412
|
+
@unless_condition_result = true
|
|
413
|
+
assert !@options[:if].call(@object)
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def test_should_be_true_if_if_condition_is_true_and_unless_condition_is_false
|
|
417
|
+
@if_condition_result = true
|
|
418
|
+
@unless_condition_result = false
|
|
419
|
+
assert @options[:if].call(@object)
|
|
420
|
+
end
|
|
421
|
+
end
|
data/test/unit/state_test.rb
CHANGED
|
@@ -561,6 +561,25 @@ class StateWithConflictingMachineTest < Test::Unit::TestCase
|
|
|
561
561
|
end
|
|
562
562
|
end
|
|
563
563
|
|
|
564
|
+
class StateWithConflictingMachineNameTest < Test::Unit::TestCase
|
|
565
|
+
def setup
|
|
566
|
+
require 'stringio'
|
|
567
|
+
@original_stderr, $stderr = $stderr, StringIO.new
|
|
568
|
+
|
|
569
|
+
@klass = Class.new
|
|
570
|
+
@state_machine = StateMachine::Machine.new(@klass, :state)
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
def test_should_output_warning_if_name_conflicts
|
|
574
|
+
StateMachine::State.new(@state_machine, :state)
|
|
575
|
+
assert_equal "Instance method \"state?\" is already defined in #{@klass} :state instance helpers, use generic helper instead.\n", $stderr.string
|
|
576
|
+
end
|
|
577
|
+
|
|
578
|
+
def teardown
|
|
579
|
+
$stderr = @original_stderr
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
|
|
564
583
|
class StateWithNamespaceTest < Test::Unit::TestCase
|
|
565
584
|
def setup
|
|
566
585
|
@klass = Class.new
|
|
@@ -794,8 +813,6 @@ end
|
|
|
794
813
|
|
|
795
814
|
begin
|
|
796
815
|
# Load library
|
|
797
|
-
require 'rubygems'
|
|
798
|
-
gem 'ruby-graphviz', '>=0.9.0'
|
|
799
816
|
require 'graphviz'
|
|
800
817
|
|
|
801
818
|
class StateDrawingTest < Test::Unit::TestCase
|
|
@@ -921,4 +938,4 @@ begin
|
|
|
921
938
|
end
|
|
922
939
|
rescue LoadError
|
|
923
940
|
$stderr.puts 'Skipping GraphViz StateMachine::State tests. `gem install ruby-graphviz` >= v0.9.0 and try again.'
|
|
924
|
-
end
|
|
941
|
+
end unless ENV['TRAVIS']
|