state_machine 0.2.1 → 0.3.0
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/CHANGELOG.rdoc +15 -0
- data/README.rdoc +64 -14
- data/Rakefile +1 -1
- data/lib/state_machine.rb +25 -28
- data/lib/state_machine/event.rb +47 -111
- data/lib/state_machine/machine.rb +302 -67
- data/lib/state_machine/transition.rb +173 -68
- data/test/app_root/app/models/auto_shop.rb +2 -2
- data/test/app_root/app/models/switch_observer.rb +20 -0
- data/test/app_root/app/models/vehicle.rb +14 -7
- data/test/app_root/config/environment.rb +7 -0
- data/test/factory.rb +6 -0
- data/test/functional/state_machine_test.rb +53 -1
- data/test/unit/event_test.rb +43 -188
- data/test/unit/machine_test.rb +154 -30
- data/test/unit/state_machine_test.rb +39 -29
- data/test/unit/transition_test.rb +347 -218
- metadata +6 -3
data/test/unit/machine_test.rb
CHANGED
@@ -26,12 +26,6 @@ class MachineByDefaultTest < Test::Unit::TestCase
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
class MachineWithInvalidOptionsTest < Test::Unit::TestCase
|
30
|
-
def test_should_throw_an_exception
|
31
|
-
assert_raise(ArgumentError) {PluginAWeek::StateMachine::Machine.new(Switch, 'state', :invalid => true)}
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
29
|
class MachineWithInitialStateTest < Test::Unit::TestCase
|
36
30
|
def setup
|
37
31
|
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state', :initial => 'off')
|
@@ -40,15 +34,11 @@ class MachineWithInitialStateTest < Test::Unit::TestCase
|
|
40
34
|
def test_should_have_an_initial_state
|
41
35
|
assert_equal 'off', @machine.initial_state(new_switch)
|
42
36
|
end
|
43
|
-
|
44
|
-
def test_should_have_an_initial_state_without_processing
|
45
|
-
assert_equal 'off', @machine.initial_state_without_processing
|
46
|
-
end
|
47
37
|
end
|
48
38
|
|
49
39
|
class MachineWithDynamicInitialStateTest < Test::Unit::TestCase
|
50
40
|
def setup
|
51
|
-
@initial_state =
|
41
|
+
@initial_state = lambda {|switch| switch.initial_state}
|
52
42
|
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state', :initial => @initial_state)
|
53
43
|
end
|
54
44
|
|
@@ -56,10 +46,6 @@ class MachineWithDynamicInitialStateTest < Test::Unit::TestCase
|
|
56
46
|
assert_equal 'off', @machine.initial_state(new_switch(:initial_state => 'off'))
|
57
47
|
assert_equal 'on', @machine.initial_state(new_switch(:initial_state => 'on'))
|
58
48
|
end
|
59
|
-
|
60
|
-
def test_should_have_an_initial_state_without_processing
|
61
|
-
assert_equal @initial_state, @machine.initial_state_without_processing
|
62
|
-
end
|
63
49
|
end
|
64
50
|
|
65
51
|
class MachineTest < Test::Unit::TestCase
|
@@ -80,6 +66,74 @@ class MachineTest < Test::Unit::TestCase
|
|
80
66
|
|
81
67
|
assert_equal [on, off], Switch.with_states('on', 'off')
|
82
68
|
end
|
69
|
+
|
70
|
+
def test_should_raise_exception_if_invalid_option_specified
|
71
|
+
assert_raise(ArgumentError) {PluginAWeek::StateMachine::Machine.new(Switch, 'state', :invalid => true)}
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_should_symbolize_attribute
|
75
|
+
machine = PluginAWeek::StateMachine::Machine.new(Switch, :state)
|
76
|
+
assert_equal 'state', machine.attribute
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class MachineAfterBeingCopiedTest < Test::Unit::TestCase
|
81
|
+
def setup
|
82
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
83
|
+
@machine.event(:turn_on) {}
|
84
|
+
|
85
|
+
@copied_machine = @machine.dup
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_should_not_have_the_same_collection_of_states
|
89
|
+
assert_not_same @copied_machine.states, @machine.states
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_should_not_have_the_same_collection_of_events
|
93
|
+
assert_not_same @copied_machine.events, @machine.events
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_should_copy_each_event
|
97
|
+
assert_not_same @copied_machine.events['turn_on'], @machine.events['turn_on']
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_should_update_machine_for_each_event
|
101
|
+
assert_equal @copied_machine, @copied_machine.events['turn_on'].machine
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_should_not_update_machine_for_original_event
|
105
|
+
assert_equal @machine, @machine.events['turn_on'].machine
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class MachineAfterChangingContextTest < Test::Unit::TestCase
|
110
|
+
def setup
|
111
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_should_create_copy_of_machine
|
115
|
+
new_machine = @machine.within_context(ToggleSwitch)
|
116
|
+
assert_not_same @machine, new_machine
|
117
|
+
end
|
118
|
+
|
119
|
+
def test_should_update_owner_clas
|
120
|
+
new_machine = @machine.within_context(ToggleSwitch)
|
121
|
+
assert_equal ToggleSwitch, new_machine.owner_class
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_should_update_initial_state
|
125
|
+
new_machine = @machine.within_context(ToggleSwitch, :initial => 'off')
|
126
|
+
assert_equal 'off', new_machine.initial_state(new_switch)
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_should_not_update_initial_state_if_not_provided
|
130
|
+
new_machine = @machine.within_context(ToggleSwitch)
|
131
|
+
assert_nil new_machine.initial_state(new_switch)
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_raise_exception_if_invalid_option_specified
|
135
|
+
assert_raise(ArgumentError) {@machine.within_context(ToggleSwitch, :invalid => true)}
|
136
|
+
end
|
83
137
|
end
|
84
138
|
|
85
139
|
class MachineWithConflictingNamedScopesTest < Test::Unit::TestCase
|
@@ -131,6 +185,18 @@ class MachineWithEventsTest < Test::Unit::TestCase
|
|
131
185
|
end
|
132
186
|
end
|
133
187
|
|
188
|
+
class MachineWithExistingEventTest < Test::Unit::TestCase
|
189
|
+
def setup
|
190
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
191
|
+
@event = @machine.event(:turn_on) {}
|
192
|
+
@same_event = @machine.event(:turn_on) {}
|
193
|
+
end
|
194
|
+
|
195
|
+
def test_should_not_create_new_event
|
196
|
+
assert_same @event, @same_event
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
134
200
|
class MachineWithEventsAndTransitionsTest < Test::Unit::TestCase
|
135
201
|
def setup
|
136
202
|
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
@@ -144,19 +210,22 @@ class MachineWithEventsAndTransitionsTest < Test::Unit::TestCase
|
|
144
210
|
assert_equal %w(turn_on), @machine.events.keys
|
145
211
|
end
|
146
212
|
|
147
|
-
def
|
148
|
-
assert_equal %w(
|
213
|
+
def test_should_track_states_defined_in_event_transitions
|
214
|
+
assert_equal %w(error off on unknown), @machine.states
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_should_not_duplicate_states_defined_in_multiple_event_transitions
|
218
|
+
@machine.event :turn_off do
|
219
|
+
transition :to => 'off', :from => 'on'
|
220
|
+
end
|
221
|
+
|
222
|
+
assert_equal %w(error off on unknown), @machine.states
|
149
223
|
end
|
150
224
|
end
|
151
225
|
|
152
|
-
class
|
226
|
+
class MachineWithTransitionCallbacksTest < Test::Unit::TestCase
|
153
227
|
def setup
|
154
228
|
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
155
|
-
@machine.before_exit 'off', Proc.new {|switch, value| switch.callbacks << 'before_exit'}
|
156
|
-
@machine.before_enter 'on', Proc.new {|switch, value| switch.callbacks << 'before_enter'}
|
157
|
-
@machine.after_exit 'off', Proc.new {|switch, value| switch.callbacks << 'after_exit'}
|
158
|
-
@machine.after_enter 'on', Proc.new {|switch, value| switch.callbacks << 'after_enter'}
|
159
|
-
|
160
229
|
@event = @machine.event :turn_on do
|
161
230
|
transition :to => 'on', :from => 'off'
|
162
231
|
end
|
@@ -164,19 +233,74 @@ class MachineWithStateCallbacksTest < Test::Unit::TestCase
|
|
164
233
|
@switch = create_switch(:state => 'off')
|
165
234
|
end
|
166
235
|
|
236
|
+
def test_should_raise_exception_if_invalid_option_specified
|
237
|
+
assert_raise(ArgumentError) {@machine.before_transition :invalid => true}
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_should_raise_exception_if_do_option_not_specified
|
241
|
+
assert_raise(ArgumentError) {@machine.before_transition :to => 'on'}
|
242
|
+
end
|
243
|
+
|
167
244
|
def test_should_invoke_callbacks_during_transition
|
245
|
+
@machine.before_transition lambda {|switch| switch.callbacks << 'before'}
|
246
|
+
@machine.after_transition lambda {|switch| switch.callbacks << 'after'}
|
247
|
+
|
248
|
+
@event.fire(@switch)
|
249
|
+
assert_equal %w(before after), @switch.callbacks
|
250
|
+
end
|
251
|
+
|
252
|
+
def test_should_support_from_query
|
253
|
+
@machine.before_transition :from => 'off', :do => lambda {|switch| switch.callbacks << 'off'}
|
254
|
+
@machine.before_transition :from => 'on', :do => lambda {|switch| switch.callbacks << 'on'}
|
255
|
+
|
256
|
+
@event.fire(@switch)
|
257
|
+
assert_equal %w(off), @switch.callbacks
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_should_support_except_from_query
|
261
|
+
@machine.before_transition :except_from => 'off', :do => lambda {|switch| switch.callbacks << 'off'}
|
262
|
+
@machine.before_transition :except_from => 'on', :do => lambda {|switch| switch.callbacks << 'on'}
|
263
|
+
|
264
|
+
@event.fire(@switch)
|
265
|
+
assert_equal %w(on), @switch.callbacks
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_should_support_to_query
|
269
|
+
@machine.before_transition :to => 'off', :do => lambda {|switch| switch.callbacks << 'off'}
|
270
|
+
@machine.before_transition :to => 'on', :do => lambda {|switch| switch.callbacks << 'on'}
|
271
|
+
|
272
|
+
@event.fire(@switch)
|
273
|
+
assert_equal %w(on), @switch.callbacks
|
274
|
+
end
|
275
|
+
|
276
|
+
def test_should_support_except_to_query
|
277
|
+
@machine.before_transition :except_to => 'off', :do => lambda {|switch| switch.callbacks << 'off'}
|
278
|
+
@machine.before_transition :except_to => 'on', :do => lambda {|switch| switch.callbacks << 'on'}
|
279
|
+
|
280
|
+
@event.fire(@switch)
|
281
|
+
assert_equal %w(off), @switch.callbacks
|
282
|
+
end
|
283
|
+
|
284
|
+
def test_should_support_on_query
|
285
|
+
@machine.before_transition :on => 'turn_off', :do => lambda {|switch| switch.callbacks << 'turn_off'}
|
286
|
+
@machine.before_transition :on => 'turn_on', :do => lambda {|switch| switch.callbacks << 'turn_on'}
|
287
|
+
|
288
|
+
@event.fire(@switch)
|
289
|
+
assert_equal %w(turn_on), @switch.callbacks
|
290
|
+
end
|
291
|
+
|
292
|
+
def test_should_support_except_on_query
|
293
|
+
@machine.before_transition :except_on => 'turn_off', :do => lambda {|switch| switch.callbacks << 'turn_off'}
|
294
|
+
@machine.before_transition :except_on => 'turn_on', :do => lambda {|switch| switch.callbacks << 'turn_on'}
|
295
|
+
|
168
296
|
@event.fire(@switch)
|
169
|
-
assert_equal %w(
|
297
|
+
assert_equal %w(turn_off), @switch.callbacks
|
170
298
|
end
|
171
299
|
|
172
300
|
def teardown
|
173
301
|
Switch.class_eval do
|
174
|
-
@
|
175
|
-
@
|
176
|
-
@before_exit_state_off_callbacks = nil
|
177
|
-
@before_enter_state_on_callbacks = nil
|
178
|
-
@after_exit_state_off_callbacks = nil
|
179
|
-
@after_enter_state_on_callbacks = nil
|
302
|
+
@before_transition_state_callbacks = nil
|
303
|
+
@after_transition_state_callbacks = nil
|
180
304
|
end
|
181
305
|
end
|
182
306
|
end
|
@@ -72,45 +72,55 @@ class StateMachineAfterInitializedWithDynamicInitialStateTest < Test::Unit::Test
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
-
class
|
75
|
+
class StateMachineWithSubclassTest < Test::Unit::TestCase
|
76
76
|
def setup
|
77
|
-
machine = Switch.state_machine(:state, :initial => '
|
77
|
+
@machine = Switch.state_machine(:state, :initial => 'on') do
|
78
|
+
event :turn_on do
|
79
|
+
transition :to => 'on', :from => 'off'
|
80
|
+
end
|
81
|
+
end
|
78
82
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
machine.after_enter 'off', Proc.new {|switch, value| switch.callbacks << 'after_enter'}
|
83
|
+
# Need to add this since the state machine isn't defined directly within the
|
84
|
+
# class
|
85
|
+
ToggleSwitch.write_inheritable_attribute :state_machines, {'state' => @machine}
|
83
86
|
|
84
|
-
@
|
87
|
+
@new_machine = ToggleSwitch.state_machine(:state, :initial => 'off') do
|
88
|
+
event :turn_on do
|
89
|
+
transition :to => 'off', :from => 'on'
|
90
|
+
end
|
91
|
+
|
92
|
+
event :replace do
|
93
|
+
transition :to => 'under_repair', :from => 'off'
|
94
|
+
end
|
95
|
+
end
|
85
96
|
end
|
86
97
|
|
87
|
-
def
|
88
|
-
|
98
|
+
def test_should_not_have_the_same_machine_as_the_superclass
|
99
|
+
assert_not_same @machine, @new_machine
|
89
100
|
end
|
90
101
|
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
Switch.class_eval do
|
95
|
-
@transition_on_turn_on_callbacks = nil
|
96
|
-
@transition_bang_on_turn_on_callbacks = nil
|
97
|
-
@before_exit_state_off_callbacks = nil
|
98
|
-
@before_enter_state_on_callbacks = nil
|
99
|
-
@after_exit_state_off_callbacks = nil
|
100
|
-
@after_enter_state_on_callbacks = nil
|
101
|
-
end
|
102
|
+
def test_should_use_new_initial_state
|
103
|
+
assert_equal 'off', @new_machine.initial_state(new_switch)
|
102
104
|
end
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
105
|
+
|
106
|
+
def test_should_not_change_original_initial_state
|
107
|
+
assert_equal 'on', @machine.initial_state(new_switch)
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_should_define_new_events_on_subclass
|
111
|
+
assert new_toggle_switch.respond_to?(:replace)
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_should_not_define_new_events_on_superclass
|
115
|
+
assert !new_switch.respond_to?(:replace)
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_should_define_new_transitions_on_subclass
|
119
|
+
assert_equal 2, @new_machine.events['turn_on'].transitions.length
|
109
120
|
end
|
110
121
|
|
111
|
-
def
|
112
|
-
assert_equal
|
113
|
-
assert_equal 'off', ToggleSwitch.new.state
|
122
|
+
def test_should_not_define_new_transitions_on_superclass
|
123
|
+
assert_equal 1, @machine.events['turn_on'].transitions.length
|
114
124
|
end
|
115
125
|
|
116
126
|
def teardown
|
@@ -2,33 +2,126 @@ require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
|
2
2
|
|
3
3
|
class TransitionTest < Test::Unit::TestCase
|
4
4
|
def setup
|
5
|
-
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state'
|
5
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
6
6
|
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
7
7
|
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on')
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
|
10
|
+
def test_should_have_an_event
|
11
|
+
assert_not_nil @transition.event
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
|
14
|
+
def test_should_have_options
|
15
|
+
assert_not_nil @transition.options
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
|
18
|
+
def test_should_match_any_from_state
|
19
|
+
assert @transition.matches?('off')
|
20
|
+
assert @transition.matches?('on')
|
20
21
|
end
|
21
22
|
|
22
|
-
def
|
23
|
-
assert @transition.
|
23
|
+
def test_should_match_empty_query
|
24
|
+
assert @transition.matches?('off', {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_match_if_from_state_included
|
28
|
+
assert @transition.matches?('off', :from => 'off')
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_should_not_match_if_from_state_not_included
|
32
|
+
assert !@transition.matches?('off', :from => 'on')
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_should_allow_matching_of_multiple_from_states
|
36
|
+
assert @transition.matches?('off', :from => %w(on off))
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_should_match_if_except_from_state_not_included
|
40
|
+
assert @transition.matches?('off', :except_from => 'on')
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_should_not_match_if_except_from_state_included
|
44
|
+
assert !@transition.matches?('off', :except_from => 'off')
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_should_allow_matching_of_multiple_except_from_states
|
48
|
+
assert @transition.matches?('off', :except_from => %w(on maybe))
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_should_match_if_to_state_included
|
52
|
+
assert @transition.matches?('off', :to => 'on')
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_should_not_match_if_to_state_not_included
|
56
|
+
assert !@transition.matches?('off', :to => 'off')
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_should_allow_matching_of_multiple_to_states
|
60
|
+
assert @transition.matches?('off', :to => %w(on off))
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_should_match_if_except_to_state_not_included
|
64
|
+
assert @transition.matches?('off', :except_to => 'off')
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_should_not_match_if_except_to_state_included
|
68
|
+
assert !@transition.matches?('off', :except_to => 'on')
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_should_allow_matching_of_multiple_except_to_states
|
72
|
+
assert @transition.matches?('off', :except_to => %w(off maybe))
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_should_match_if_on_event_included
|
76
|
+
assert @transition.matches?('off', :on => 'turn_on')
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_should_not_match_if_on_event_not_included
|
80
|
+
assert !@transition.matches?('off', :on => 'turn_off')
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_should_allow_matching_of_multiple_on_events
|
84
|
+
assert @transition.matches?('off', :on => %w(turn_off turn_on))
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_should_match_if_except_on_event_not_included
|
88
|
+
assert @transition.matches?('off', :except_on => 'turn_off')
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_should_not_match_if_except_on_event_included
|
92
|
+
assert !@transition.matches?('off', :except_on => 'turn_on')
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_should_allow_matching_of_multiple_except_on_events
|
96
|
+
assert @transition.matches?('off', :except_on => %w(turn_off not_sure))
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_should_match_if_from_state_and_to_state_match
|
100
|
+
assert @transition.matches?('off', :from => 'off', :to => 'on')
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_should_not_match_if_from_state_matches_but_not_to_state
|
104
|
+
assert !@transition.matches?('off', :from => 'off', :to => 'off')
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_should_not_match_if_to_state_matches_but_not_from_state
|
108
|
+
assert !@transition.matches?('off', :from => 'on', :to => 'on')
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_should_match_if_from_state_to_state_and_on_event_match
|
112
|
+
assert @transition.matches?('off', :from => 'off', :to => 'on', :on => 'turn_on')
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_should_not_match_if_from_state_and_to_state_match_but_not_on_event
|
116
|
+
assert !@transition.matches?('off', :from => 'off', :to => 'on', :on => 'turn_off')
|
24
117
|
end
|
25
118
|
|
26
119
|
def test_should_be_able_to_perform_on_all_states
|
27
120
|
record = new_switch(:state => 'off')
|
28
|
-
assert @transition.
|
121
|
+
assert @transition.can_perform?(record)
|
29
122
|
|
30
123
|
record = new_switch(:state => 'on')
|
31
|
-
assert @transition.
|
124
|
+
assert @transition.can_perform?(record)
|
32
125
|
end
|
33
126
|
|
34
127
|
def test_should_perform_for_all_states
|
@@ -76,16 +169,61 @@ class TransitionTest < Test::Unit::TestCase
|
|
76
169
|
end
|
77
170
|
end
|
78
171
|
|
172
|
+
class TransitionWithConditionalTest < Test::Unit::TestCase
|
173
|
+
def setup
|
174
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
175
|
+
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
176
|
+
@switch = create_switch(:state => 'off')
|
177
|
+
end
|
178
|
+
|
179
|
+
def test_should_be_able_to_perform_if_if_is_true
|
180
|
+
transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :if => lambda {true})
|
181
|
+
assert transition.can_perform?(@switch)
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_should_not_be_able_to_perform_if_if_is_false
|
185
|
+
transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :if => lambda {false})
|
186
|
+
assert !transition.can_perform?(@switch)
|
187
|
+
end
|
188
|
+
|
189
|
+
def test_should_be_able_to_perform_if_unless_is_false
|
190
|
+
transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :unless => lambda {false})
|
191
|
+
assert transition.can_perform?(@switch)
|
192
|
+
end
|
193
|
+
|
194
|
+
def test_should_not_be_able_to_perform_if_unless_is_true
|
195
|
+
transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :unless => lambda {true})
|
196
|
+
assert !transition.can_perform?(@switch)
|
197
|
+
end
|
198
|
+
|
199
|
+
def test_should_pass_in_record_as_argument
|
200
|
+
transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :if => lambda {|record| !record.nil?})
|
201
|
+
assert transition.can_perform?(@switch)
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_should_be_able_to_perform_if_method_evaluates_to_true
|
205
|
+
@switch.data = true
|
206
|
+
transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :if => :data)
|
207
|
+
assert transition.can_perform?(@switch)
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_should_not_be_able_to_perform_if_method_evaluates_to_false
|
211
|
+
@switch.data = false
|
212
|
+
transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :if => :data)
|
213
|
+
assert !transition.can_perform?(@switch)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
79
217
|
class TransitionWithLoopbackTest < Test::Unit::TestCase
|
80
218
|
def setup
|
81
|
-
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state'
|
219
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
82
220
|
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
83
221
|
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :from => 'on')
|
84
222
|
end
|
85
223
|
|
86
224
|
def test_should_be_able_to_perform
|
87
225
|
record = new_switch(:state => 'on')
|
88
|
-
assert @transition.
|
226
|
+
assert @transition.can_perform?(record)
|
89
227
|
end
|
90
228
|
|
91
229
|
def test_should_perform_for_valid_from_state
|
@@ -96,23 +234,19 @@ end
|
|
96
234
|
|
97
235
|
class TransitionWithFromStateTest < Test::Unit::TestCase
|
98
236
|
def setup
|
99
|
-
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state'
|
237
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
100
238
|
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
101
239
|
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :from => 'off')
|
102
240
|
end
|
103
241
|
|
104
|
-
def test_should_have_a_from_state
|
105
|
-
assert_equal ['off'], @transition.from_states
|
106
|
-
end
|
107
|
-
|
108
242
|
def test_should_not_be_able_to_perform_if_record_state_is_not_from_state
|
109
243
|
record = new_switch(:state => 'on')
|
110
|
-
assert !@transition.
|
244
|
+
assert !@transition.can_perform?(record)
|
111
245
|
end
|
112
246
|
|
113
247
|
def test_should_be_able_to_perform_if_record_state_is_from_state
|
114
248
|
record = new_switch(:state => 'off')
|
115
|
-
assert @transition.
|
249
|
+
assert @transition.can_perform?(record)
|
116
250
|
end
|
117
251
|
|
118
252
|
def test_should_perform_for_valid_from_state
|
@@ -123,26 +257,22 @@ end
|
|
123
257
|
|
124
258
|
class TransitionWithMultipleFromStatesTest < Test::Unit::TestCase
|
125
259
|
def setup
|
126
|
-
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state'
|
260
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
127
261
|
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
128
262
|
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :from => %w(off on))
|
129
263
|
end
|
130
264
|
|
131
|
-
def test_should_have_multiple_from_states
|
132
|
-
assert_equal ['off', 'on'], @transition.from_states
|
133
|
-
end
|
134
|
-
|
135
265
|
def test_should_not_be_able_to_perform_if_record_state_is_not_from_state
|
136
266
|
record = new_switch(:state => 'unknown')
|
137
|
-
assert !@transition.
|
267
|
+
assert !@transition.can_perform?(record)
|
138
268
|
end
|
139
269
|
|
140
270
|
def test_should_be_able_to_perform_if_record_state_is_any_from_state
|
141
271
|
record = new_switch(:state => 'off')
|
142
|
-
assert @transition.
|
272
|
+
assert @transition.can_perform?(record)
|
143
273
|
|
144
274
|
record = new_switch(:state => 'on')
|
145
|
-
assert @transition.
|
275
|
+
assert @transition.can_perform?(record)
|
146
276
|
end
|
147
277
|
|
148
278
|
def test_should_perform_for_any_valid_from_state
|
@@ -156,23 +286,19 @@ end
|
|
156
286
|
|
157
287
|
class TransitionWithMismatchedFromStatesRequiredTest < Test::Unit::TestCase
|
158
288
|
def setup
|
159
|
-
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state'
|
289
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
160
290
|
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
161
291
|
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :except_from => 'on')
|
162
292
|
end
|
163
293
|
|
164
|
-
def test_should_have_a_from_state
|
165
|
-
assert_equal ['on'], @transition.from_states
|
166
|
-
end
|
167
|
-
|
168
294
|
def test_should_be_able_to_perform_if_record_state_is_not_from_state
|
169
295
|
record = new_switch(:state => 'off')
|
170
|
-
assert @transition.
|
296
|
+
assert @transition.can_perform?(record)
|
171
297
|
end
|
172
298
|
|
173
299
|
def test_should_not_be_able_to_perform_if_record_state_is_from_state
|
174
300
|
record = new_switch(:state => 'on')
|
175
|
-
assert !@transition.
|
301
|
+
assert !@transition.can_perform?(record)
|
176
302
|
end
|
177
303
|
|
178
304
|
def test_should_perform_for_valid_from_state
|
@@ -182,13 +308,13 @@ class TransitionWithMismatchedFromStatesRequiredTest < Test::Unit::TestCase
|
|
182
308
|
|
183
309
|
def test_should_not_perform_for_invalid_from_state
|
184
310
|
record = new_switch(:state => 'on')
|
185
|
-
assert !@transition.
|
311
|
+
assert !@transition.can_perform?(record)
|
186
312
|
end
|
187
313
|
end
|
188
314
|
|
189
315
|
class TransitionAfterBeingPerformedTest < Test::Unit::TestCase
|
190
316
|
def setup
|
191
|
-
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state'
|
317
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
192
318
|
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
193
319
|
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :from => 'off')
|
194
320
|
|
@@ -202,303 +328,306 @@ class TransitionAfterBeingPerformedTest < Test::Unit::TestCase
|
|
202
328
|
end
|
203
329
|
|
204
330
|
def test_should_no_longer_be_able_to_perform_on_the_record
|
205
|
-
assert !@transition.
|
331
|
+
assert !@transition.can_perform?(@record)
|
206
332
|
end
|
207
333
|
end
|
208
334
|
|
209
335
|
class TransitionWithLoopbackAfterBeingPerformedTest < Test::Unit::TestCase
|
210
336
|
def setup
|
211
|
-
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state'
|
337
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
212
338
|
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
213
339
|
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :from => 'on')
|
214
340
|
|
215
341
|
@record = create_switch(:state => 'on')
|
342
|
+
@record.kind = 'light'
|
216
343
|
@transition.perform(@record)
|
217
344
|
@record.reload
|
218
345
|
end
|
219
346
|
|
220
|
-
def
|
347
|
+
def test_should_have_the_same_attribute
|
221
348
|
assert_equal 'on', @record.state
|
222
349
|
end
|
223
350
|
|
351
|
+
def test_should_save_the_record
|
352
|
+
assert_equal 'light', @record.kind
|
353
|
+
end
|
354
|
+
|
224
355
|
def test_should_still_be_able_to_perform_on_the_record
|
225
|
-
assert @transition.
|
356
|
+
assert @transition.can_perform?(@record)
|
226
357
|
end
|
227
358
|
end
|
228
359
|
|
229
360
|
class TransitionWithCallbacksTest < Test::Unit::TestCase
|
230
361
|
def setup
|
231
|
-
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state'
|
362
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
232
363
|
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
233
364
|
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :from => 'off')
|
234
365
|
@record = create_switch(:state => 'off')
|
235
366
|
|
236
|
-
Switch.define_callbacks :
|
237
|
-
end
|
238
|
-
|
239
|
-
def test_should_not_perform_if_before_exit_callback_fails
|
240
|
-
Switch.before_exit_state_off Proc.new {|record| false}
|
241
|
-
Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
|
242
|
-
Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
|
243
|
-
Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
|
244
|
-
|
245
|
-
assert !@transition.perform(@record)
|
246
|
-
assert_equal [], @record.callbacks
|
367
|
+
Switch.define_callbacks :before_transition_state, :after_transition_state
|
247
368
|
end
|
248
369
|
|
249
|
-
def
|
250
|
-
Switch.
|
370
|
+
def test_should_include_record_in_callback
|
371
|
+
Switch.before_transition_state lambda {|record| record == @record}
|
251
372
|
|
252
|
-
|
373
|
+
assert @transition.perform(@record)
|
253
374
|
end
|
254
375
|
|
255
|
-
def
|
256
|
-
Switch.
|
257
|
-
Switch.
|
258
|
-
Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
|
259
|
-
Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
|
376
|
+
def test_should_not_perform_if_before_callback_fails
|
377
|
+
Switch.before_transition_state lambda {|record| false}
|
378
|
+
Switch.after_transition_state lambda {|record| record.callbacks << 'after'; true}
|
260
379
|
|
261
380
|
assert !@transition.perform(@record)
|
262
|
-
assert_equal
|
381
|
+
assert_equal [], @record.callbacks
|
263
382
|
end
|
264
383
|
|
265
|
-
def
|
266
|
-
Switch.
|
267
|
-
Switch.before_enter_state_on Proc.new {|record| false}
|
384
|
+
def test_should_raise_exception_if_before_callback_fails_during_perform!
|
385
|
+
Switch.before_transition_state lambda {|record| false}
|
268
386
|
|
269
387
|
assert_raise(PluginAWeek::StateMachine::InvalidTransition) {@transition.perform!(@record)}
|
270
388
|
end
|
271
389
|
|
272
|
-
def
|
273
|
-
Switch.
|
274
|
-
Switch.
|
275
|
-
Switch.after_exit_state_off Proc.new {|record| false}
|
276
|
-
Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
|
390
|
+
def test_should_perform_if_after_callback_fails
|
391
|
+
Switch.before_transition_state lambda {|record| record.callbacks << 'before'; true}
|
392
|
+
Switch.after_transition_state lambda {|record| false}
|
277
393
|
|
278
394
|
assert @transition.perform(@record)
|
279
|
-
assert_equal %w(
|
395
|
+
assert_equal %w(before), @record.callbacks
|
280
396
|
end
|
281
397
|
|
282
|
-
def
|
283
|
-
Switch.
|
284
|
-
Switch.
|
285
|
-
Switch.after_exit_state_off Proc.new {|record| false}
|
286
|
-
Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
|
398
|
+
def test_should_not_raise_exception_if_after_callback_fails_during_perform!
|
399
|
+
Switch.before_transition_state lambda {|record| record.callbacks << 'before'; true}
|
400
|
+
Switch.after_transition_state lambda {|record| false}
|
287
401
|
|
288
402
|
assert @transition.perform!(@record)
|
289
403
|
end
|
290
404
|
|
291
|
-
def
|
292
|
-
Switch.
|
293
|
-
Switch.
|
294
|
-
Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
|
295
|
-
Switch.after_enter_state_on Proc.new {|record| false}
|
405
|
+
def test_should_perform_if_all_callbacks_are_successful
|
406
|
+
Switch.before_transition_state lambda {|record| record.callbacks << 'before'; true}
|
407
|
+
Switch.after_transition_state lambda {|record| record.callbacks << 'after'; true}
|
296
408
|
|
297
409
|
assert @transition.perform(@record)
|
298
|
-
assert_equal %w(
|
410
|
+
assert_equal %w(before after), @record.callbacks
|
299
411
|
end
|
300
412
|
|
301
|
-
def
|
302
|
-
Switch.
|
303
|
-
Switch.
|
304
|
-
Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
|
305
|
-
Switch.after_enter_state_on Proc.new {|record| false}
|
413
|
+
def test_should_stop_before_callbacks_if_any_fail
|
414
|
+
Switch.before_transition_state lambda {|record| false}
|
415
|
+
Switch.before_transition_state lambda {|record| record.callbacks << 'before_2'; true}
|
306
416
|
|
307
|
-
assert
|
417
|
+
assert !@transition.perform(@record)
|
418
|
+
assert_equal [], @record.callbacks
|
308
419
|
end
|
309
420
|
|
310
|
-
def
|
311
|
-
Switch.
|
312
|
-
Switch.
|
313
|
-
Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
|
314
|
-
Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
|
421
|
+
def test_should_stop_after_callbacks_if_any_fail
|
422
|
+
Switch.after_transition_state lambda {|record| false}
|
423
|
+
Switch.after_transition_state lambda {|record| record.callbacks << 'after_2'; true}
|
315
424
|
|
316
425
|
assert @transition.perform(@record)
|
317
|
-
assert_equal
|
426
|
+
assert_equal [], @record.callbacks
|
318
427
|
end
|
319
428
|
|
320
|
-
def
|
321
|
-
Switch.
|
322
|
-
|
429
|
+
def teardown
|
430
|
+
Switch.class_eval do
|
431
|
+
@before_transition_state_callbacks = nil
|
432
|
+
@after_transition_state_callbacks = nil
|
433
|
+
end
|
434
|
+
end
|
435
|
+
end
|
436
|
+
|
437
|
+
class TransitionWithCallbackConditionalsTest < Test::Unit::TestCase
|
438
|
+
def setup
|
439
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
440
|
+
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
441
|
+
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :from => 'off')
|
442
|
+
@record = create_switch(:state => 'off')
|
443
|
+
@invoked = false
|
323
444
|
|
324
|
-
|
325
|
-
assert_equal [], @record.callbacks
|
445
|
+
Switch.define_callbacks :before_transition_state, :after_transition_state
|
326
446
|
end
|
327
447
|
|
328
|
-
def
|
329
|
-
Switch.
|
330
|
-
|
331
|
-
|
332
|
-
assert !@transition.perform(@record)
|
333
|
-
assert_equal [], @record.callbacks
|
448
|
+
def test_should_invoke_callback_if_if_is_true
|
449
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :if => lambda {true}
|
450
|
+
@transition.perform(@record)
|
451
|
+
assert @invoked
|
334
452
|
end
|
335
453
|
|
336
|
-
def
|
337
|
-
Switch.
|
338
|
-
|
339
|
-
|
340
|
-
assert @transition.perform(@record)
|
341
|
-
assert_equal [], @record.callbacks
|
454
|
+
def test_should_not_invoke_callback_if_if_is_false
|
455
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :if => lambda {false}
|
456
|
+
@transition.perform(@record)
|
457
|
+
assert !@invoked
|
342
458
|
end
|
343
459
|
|
344
|
-
def
|
345
|
-
Switch.
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
460
|
+
def test_should_invoke_callback_if_unless_is_false
|
461
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :unless => lambda {false}
|
462
|
+
@transition.perform(@record)
|
463
|
+
assert @invoked
|
464
|
+
end
|
465
|
+
|
466
|
+
def test_should_not_invoke_callback_if_unless_is_true
|
467
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :unless => lambda {true}
|
468
|
+
@transition.perform(@record)
|
469
|
+
assert !@invoked
|
350
470
|
end
|
351
471
|
|
352
472
|
def teardown
|
353
473
|
Switch.class_eval do
|
354
|
-
@
|
355
|
-
@
|
356
|
-
@after_exit_state_off_callbacks = nil
|
357
|
-
@after_enter_state_on_callbacks = nil
|
474
|
+
@before_transition_state_callbacks = nil
|
475
|
+
@after_transition_state_callbacks = nil
|
358
476
|
end
|
359
477
|
end
|
360
478
|
end
|
361
479
|
|
362
|
-
class
|
480
|
+
class TransitionWithCallbackQueryTest < Test::Unit::TestCase
|
363
481
|
def setup
|
364
|
-
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state'
|
482
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
365
483
|
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
366
|
-
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on')
|
484
|
+
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :from => 'off')
|
367
485
|
@record = create_switch(:state => 'off')
|
368
486
|
|
369
|
-
Switch.define_callbacks :
|
487
|
+
Switch.define_callbacks :before_transition_state, :after_transition_state
|
370
488
|
end
|
371
489
|
|
372
|
-
def
|
373
|
-
Switch.
|
374
|
-
|
375
|
-
|
376
|
-
Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
|
377
|
-
|
378
|
-
assert !@transition.perform(@record)
|
379
|
-
assert_equal [], @record.callbacks
|
490
|
+
def test_should_invoke_callback_if_from_state_included
|
491
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :from => 'off'
|
492
|
+
@transition.perform(@record)
|
493
|
+
assert @invoked
|
380
494
|
end
|
381
495
|
|
382
|
-
def
|
383
|
-
Switch.
|
384
|
-
|
385
|
-
|
386
|
-
Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
|
387
|
-
|
388
|
-
assert !@transition.perform(@record)
|
389
|
-
assert_equal %w(before_exit), @record.callbacks
|
496
|
+
def test_should_not_invoke_callback_if_from_state_not_included
|
497
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :from => 'on'
|
498
|
+
@transition.perform(@record)
|
499
|
+
assert !@invoked
|
390
500
|
end
|
391
501
|
|
392
|
-
def
|
393
|
-
Switch.
|
394
|
-
|
395
|
-
|
396
|
-
Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
|
397
|
-
|
398
|
-
assert @transition.perform(@record)
|
399
|
-
assert_equal %w(before_exit before_enter after_enter), @record.callbacks
|
502
|
+
def test_should_invoke_callback_if_except_from_state_not_included
|
503
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :except_from => 'on'
|
504
|
+
@transition.perform(@record)
|
505
|
+
assert @invoked
|
400
506
|
end
|
401
507
|
|
402
|
-
def
|
403
|
-
Switch.
|
404
|
-
|
405
|
-
|
406
|
-
Switch.after_enter_state_on Proc.new {|record| false}
|
407
|
-
|
408
|
-
assert @transition.perform(@record)
|
409
|
-
assert_equal %w(before_exit before_enter after_exit), @record.callbacks
|
508
|
+
def test_should_not_invoke_callback_if_except_from_state_included
|
509
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :except_from => 'off'
|
510
|
+
@transition.perform(@record)
|
511
|
+
assert !@invoked
|
410
512
|
end
|
411
513
|
|
412
|
-
def
|
413
|
-
Switch.
|
414
|
-
|
415
|
-
|
416
|
-
Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
|
417
|
-
|
418
|
-
assert @transition.perform(@record)
|
419
|
-
assert_equal %w(before_exit before_enter after_exit after_enter), @record.callbacks
|
514
|
+
def test_should_invoke_callback_if_to_state_included
|
515
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :to => 'on'
|
516
|
+
@transition.perform(@record)
|
517
|
+
assert @invoked
|
420
518
|
end
|
421
519
|
|
422
|
-
def
|
423
|
-
Switch.
|
424
|
-
|
425
|
-
|
426
|
-
assert !@transition.perform(@record)
|
427
|
-
assert_equal [], @record.callbacks
|
520
|
+
def test_should_not_invoke_callback_if_to_state_not_included
|
521
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :to => 'off'
|
522
|
+
@transition.perform(@record)
|
523
|
+
assert !@invoked
|
428
524
|
end
|
429
525
|
|
430
|
-
def
|
431
|
-
Switch.
|
432
|
-
|
433
|
-
|
434
|
-
assert !@transition.perform(@record)
|
435
|
-
assert_equal [], @record.callbacks
|
526
|
+
def test_should_invoke_callback_if_except_to_state_not_included
|
527
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :except_to => 'off'
|
528
|
+
@transition.perform(@record)
|
529
|
+
assert @invoked
|
436
530
|
end
|
437
531
|
|
438
|
-
def
|
439
|
-
Switch.
|
440
|
-
|
441
|
-
|
442
|
-
assert @transition.perform(@record)
|
443
|
-
assert_equal [], @record.callbacks
|
532
|
+
def test_should_not_invoke_callback_if_except_to_state_included
|
533
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :except_to => 'on'
|
534
|
+
@transition.perform(@record)
|
535
|
+
assert !@invoked
|
444
536
|
end
|
445
537
|
|
446
|
-
def
|
447
|
-
Switch.
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
538
|
+
def test_should_invoke_callback_if_on_event_included
|
539
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :on => 'turn_on'
|
540
|
+
@transition.perform(@record)
|
541
|
+
assert @invoked
|
542
|
+
end
|
543
|
+
|
544
|
+
def test_should_not_invoke_callback_if_on_event_not_included
|
545
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :on => 'turn_off'
|
546
|
+
@transition.perform(@record)
|
547
|
+
assert !@invoked
|
548
|
+
end
|
549
|
+
|
550
|
+
def test_should_invoke_callback_if_except_on_event_not_included
|
551
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :except_on => 'turn_off'
|
552
|
+
@transition.perform(@record)
|
553
|
+
assert @invoked
|
554
|
+
end
|
555
|
+
|
556
|
+
def test_should_not_invoke_callback_if_except_on_event_included
|
557
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :except_on => 'turn_on'
|
558
|
+
@transition.perform(@record)
|
559
|
+
assert !@invoked
|
560
|
+
end
|
561
|
+
|
562
|
+
def test_should_skip_callbacks_that_do_not_match
|
563
|
+
Switch.before_transition_state lambda {|record| false}, :from => 'on'
|
564
|
+
Switch.before_transition_state lambda {|record| @invoked = true}, :from => 'off'
|
565
|
+
@transition.perform(@record)
|
566
|
+
assert @invoked
|
452
567
|
end
|
453
568
|
|
454
569
|
def teardown
|
455
570
|
Switch.class_eval do
|
456
|
-
@
|
457
|
-
@
|
458
|
-
@after_exit_state_off_callbacks = nil
|
459
|
-
@after_enter_state_on_callbacks = nil
|
571
|
+
@before_transition_state_callbacks = nil
|
572
|
+
@after_transition_state_callbacks = nil
|
460
573
|
end
|
461
574
|
end
|
462
575
|
end
|
463
576
|
|
464
|
-
class
|
577
|
+
class TransitionWithObserversTest < Test::Unit::TestCase
|
465
578
|
def setup
|
466
|
-
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state'
|
579
|
+
@machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state')
|
467
580
|
@event = PluginAWeek::StateMachine::Event.new(@machine, 'turn_on')
|
468
|
-
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :from => '
|
469
|
-
@record = create_switch(:state => '
|
470
|
-
|
471
|
-
Switch.define_callbacks :before_exit_state_off, :before_enter_state_on, :after_exit_state_off, :after_enter_state_on
|
472
|
-
Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
|
473
|
-
Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
|
474
|
-
Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
|
475
|
-
Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
|
581
|
+
@transition = PluginAWeek::StateMachine::Transition.new(@event, :to => 'on', :from => 'off')
|
582
|
+
@record = create_switch(:state => 'off')
|
476
583
|
|
477
|
-
|
584
|
+
Switch.define_callbacks :before_transition_state, :after_transition_state
|
585
|
+
SwitchObserver.notifications = []
|
478
586
|
end
|
479
587
|
|
480
|
-
def
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
588
|
+
def test_should_notify_all_callbacks_if_successful
|
589
|
+
@transition.perform(@record)
|
590
|
+
|
591
|
+
expected = [
|
592
|
+
['before_turn_on', @record, 'off', 'on'],
|
593
|
+
['before_transition', @record, 'state', 'turn_on', 'off', 'on'],
|
594
|
+
['after_turn_on', @record, 'off', 'on'],
|
595
|
+
['after_transition', @record, 'state', 'turn_on', 'off', 'on']
|
596
|
+
]
|
597
|
+
|
598
|
+
assert_equal expected, SwitchObserver.notifications
|
486
599
|
end
|
487
600
|
|
488
|
-
def
|
489
|
-
|
601
|
+
def test_should_notify_before_callbacks_if_before_callback_fails
|
602
|
+
Switch.before_transition_state lambda {|record| false}
|
603
|
+
@transition.perform(@record)
|
604
|
+
|
605
|
+
expected = [
|
606
|
+
['before_turn_on', @record, 'off', 'on'],
|
607
|
+
['before_transition', @record, 'state', 'turn_on', 'off', 'on']
|
608
|
+
]
|
609
|
+
|
610
|
+
assert_equal expected, SwitchObserver.notifications
|
490
611
|
end
|
491
612
|
|
492
|
-
def
|
493
|
-
|
613
|
+
def test_should_notify_before_and_after_callbacks_if_after_callback_fails
|
614
|
+
Switch.after_transition_state lambda {|record| false}
|
615
|
+
@transition.perform(@record)
|
616
|
+
|
617
|
+
expected = [
|
618
|
+
['before_turn_on', @record, 'off', 'on'],
|
619
|
+
['before_transition', @record, 'state', 'turn_on', 'off', 'on'],
|
620
|
+
['after_turn_on', @record, 'off', 'on'],
|
621
|
+
['after_transition', @record, 'state', 'turn_on', 'off', 'on']
|
622
|
+
]
|
623
|
+
|
624
|
+
assert_equal expected, SwitchObserver.notifications
|
494
625
|
end
|
495
626
|
|
496
627
|
def teardown
|
497
628
|
Switch.class_eval do
|
498
|
-
@
|
499
|
-
@
|
500
|
-
@after_exit_state_off_callbacks = nil
|
501
|
-
@after_enter_state_on_callbacks = nil
|
629
|
+
@before_transition_state_callbacks = nil
|
630
|
+
@after_transition_state_callbacks = nil
|
502
631
|
end
|
503
632
|
end
|
504
633
|
end
|