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.
@@ -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 = Proc.new {|switch| switch.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 test_should_have_states
148
- assert_equal %w(on off error unknown), @machine.states
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 MachineWithStateCallbacksTest < Test::Unit::TestCase
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(before_exit before_enter after_exit after_enter), @switch.callbacks
297
+ assert_equal %w(turn_off), @switch.callbacks
170
298
  end
171
299
 
172
300
  def teardown
173
301
  Switch.class_eval do
174
- @transition_on_turn_on_callbacks = nil
175
- @transition_bang_on_turn_on_callbacks = nil
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 StateMachineAfterCreatedTest < Test::Unit::TestCase
75
+ class StateMachineWithSubclassTest < Test::Unit::TestCase
76
76
  def setup
77
- machine = Switch.state_machine(:state, :initial => 'off')
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
- machine.before_exit 'off', Proc.new {|switch, value| switch.callbacks << 'before_exit'}
80
- machine.before_enter 'off', Proc.new {|switch, value| switch.callbacks << 'before_enter'}
81
- machine.after_exit 'off', Proc.new {|switch, value| switch.callbacks << 'after_exit'}
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
- @switch = create_switch
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 test_should_invoke_after_enter_callbacks_for_initial_state
88
- assert_equal %w(after_enter), @switch.callbacks
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 teardown
92
- Switch.write_inheritable_attribute(:state_machines, {})
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
- end
104
-
105
- class StateMachineWithSubclassTest < Test::Unit::TestCase
106
- def setup
107
- Switch.state_machine(:state, :initial => 'on')
108
- ToggleSwitch.state_machine(:state, :initial => 'off')
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 test_should_be_able_to_override_initial_state
112
- assert_equal 'on', Switch.new.state
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', :initial => 'off')
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 test_should_not_have_any_from_states
11
- assert @transition.from_states.empty?
10
+ def test_should_have_an_event
11
+ assert_not_nil @transition.event
12
12
  end
13
13
 
14
- def test_should_not_be_a_loopback_if_from_state_is_different
15
- assert !@transition.loopback?('off')
14
+ def test_should_have_options
15
+ assert_not_nil @transition.options
16
16
  end
17
17
 
18
- def test_should_have_a_to_state
19
- assert_equal 'on', @transition.to_state
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 test_should_be_loopback_if_from_state_is_same
23
- assert @transition.loopback?('on')
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.can_perform_on?(record)
121
+ assert @transition.can_perform?(record)
29
122
 
30
123
  record = new_switch(:state => 'on')
31
- assert @transition.can_perform_on?(record)
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', :initial => 'off')
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.can_perform_on?(record)
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', :initial => 'off')
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.can_perform_on?(record)
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.can_perform_on?(record)
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', :initial => 'off')
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.can_perform_on?(record)
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.can_perform_on?(record)
272
+ assert @transition.can_perform?(record)
143
273
 
144
274
  record = new_switch(:state => 'on')
145
- assert @transition.can_perform_on?(record)
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', :initial => 'off')
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.can_perform_on?(record)
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.can_perform_on?(record)
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.can_perform_on?(record)
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', :initial => 'off')
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.can_perform_on?(@record)
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', :initial => 'off')
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 test_should_not_update_the_attribute
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.can_perform_on?(@record)
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', :initial => 'off')
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 :before_exit_state_off, :before_enter_state_on, :after_exit_state_off, :after_enter_state_on
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 test_should_raise_exception_if_before_exit_callback_fails_during_perform!
250
- Switch.before_exit_state_off Proc.new {|record| false}
370
+ def test_should_include_record_in_callback
371
+ Switch.before_transition_state lambda {|record| record == @record}
251
372
 
252
- assert_raise(PluginAWeek::StateMachine::InvalidTransition) {@transition.perform!(@record)}
373
+ assert @transition.perform(@record)
253
374
  end
254
375
 
255
- def test_should_not_perform_if_before_enter_callback_fails
256
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
257
- Switch.before_enter_state_on Proc.new {|record| false}
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 %w(before_exit), @record.callbacks
381
+ assert_equal [], @record.callbacks
263
382
  end
264
383
 
265
- def test_should_raise_exception_if_after_enter_callback_fails_during_perform!
266
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
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 test_should_perform_if_after_exit_callback_fails
273
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
274
- Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
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(before_exit before_enter after_enter), @record.callbacks
395
+ assert_equal %w(before), @record.callbacks
280
396
  end
281
397
 
282
- def test_should_not_raise_exception_if_after_exit_callback_fails_during_perform!
283
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
284
- Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
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 test_should_perform_if_after_enter_callback_fails
292
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
293
- Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
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(before_exit before_enter after_exit), @record.callbacks
410
+ assert_equal %w(before after), @record.callbacks
299
411
  end
300
412
 
301
- def test_should_not_raise_exception_if_after_enter_callback_fails_during_perform!
302
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
303
- Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
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 @transition.perform!(@record)
417
+ assert !@transition.perform(@record)
418
+ assert_equal [], @record.callbacks
308
419
  end
309
420
 
310
- def test_should_perform_if_all_callbacks_are_successful
311
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
312
- Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
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 %w(before_exit before_enter after_exit after_enter), @record.callbacks
426
+ assert_equal [], @record.callbacks
318
427
  end
319
428
 
320
- def test_should_stop_before_exit_callbacks_if_any_fail
321
- Switch.before_exit_state_off Proc.new {|record| false}
322
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
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
- assert !@transition.perform(@record)
325
- assert_equal [], @record.callbacks
445
+ Switch.define_callbacks :before_transition_state, :after_transition_state
326
446
  end
327
447
 
328
- def test_should_stop_before_enter_callbacks_if_any_fail
329
- Switch.before_enter_state_on Proc.new {|record| false}
330
- Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
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 test_should_stop_after_exit_callbacks_if_any_fail
337
- Switch.after_exit_state_off Proc.new {|record| false}
338
- Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
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 test_should_stop_after_enter_callbacks_if_any_fail
345
- Switch.after_enter_state_on Proc.new {|record| false}
346
- Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
347
-
348
- assert @transition.perform(@record)
349
- assert_equal [], @record.callbacks
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
- @before_exit_state_off_callbacks = nil
355
- @before_enter_state_on_callbacks = nil
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 TransitionWithoutFromStateAndCallbacksTest < Test::Unit::TestCase
480
+ class TransitionWithCallbackQueryTest < Test::Unit::TestCase
363
481
  def setup
364
- @machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state', :initial => 'off')
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 :before_exit_state_off, :before_enter_state_on, :after_exit_state_off, :after_enter_state_on
487
+ Switch.define_callbacks :before_transition_state, :after_transition_state
370
488
  end
371
489
 
372
- def test_should_not_perform_if_before_exit_callback_fails
373
- Switch.before_exit_state_off Proc.new {|record| false}
374
- Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
375
- Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
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 test_should_not_perform_if_before_enter_callback_fails
383
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
384
- Switch.before_enter_state_on Proc.new {|record| false}
385
- Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
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 test_should_perform_if_after_exit_callback_fails
393
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
394
- Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
395
- Switch.after_exit_state_off Proc.new {|record| false}
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 test_should_perform_if_after_enter_callback_fails
403
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
404
- Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
405
- Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
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 test_should_perform_if_all_callbacks_are_successful
413
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
414
- Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
415
- Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
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 test_should_stop_before_exit_callbacks_if_any_fail
423
- Switch.before_exit_state_off Proc.new {|record| false}
424
- Switch.before_exit_state_off Proc.new {|record| record.callbacks << 'before_exit'; true}
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 test_should_stop_before_enter_callbacks_if_any_fail
431
- Switch.before_enter_state_on Proc.new {|record| false}
432
- Switch.before_enter_state_on Proc.new {|record| record.callbacks << 'before_enter'; true}
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 test_should_stop_after_exit_callbacks_if_any_fail
439
- Switch.after_exit_state_off Proc.new {|record| false}
440
- Switch.after_exit_state_off Proc.new {|record| record.callbacks << 'after_exit'; true}
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 test_should_stop_after_enter_callbacks_if_any_fail
447
- Switch.after_enter_state_on Proc.new {|record| false}
448
- Switch.after_enter_state_on Proc.new {|record| record.callbacks << 'after_enter'; true}
449
-
450
- assert @transition.perform(@record)
451
- assert_equal [], @record.callbacks
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
- @before_exit_state_off_callbacks = nil
457
- @before_enter_state_on_callbacks = nil
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 TransitionWithLoopbackAndCallbacksTest < Test::Unit::TestCase
577
+ class TransitionWithObserversTest < Test::Unit::TestCase
465
578
  def setup
466
- @machine = PluginAWeek::StateMachine::Machine.new(Switch, 'state', :initial => 'off')
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 => 'on')
469
- @record = create_switch(:state => 'on')
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
- assert @transition.perform(@record)
584
+ Switch.define_callbacks :before_transition_state, :after_transition_state
585
+ SwitchObserver.notifications = []
478
586
  end
479
587
 
480
- def test_should_not_run_before_exit_callbacks
481
- assert !@record.callbacks.include?('before_exit')
482
- end
483
-
484
- def test_should_not_run_before_enter_callbacks
485
- assert !@record.callbacks.include?('before_enter')
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 test_should_not_run_after_exit_callbacks
489
- assert !@record.callbacks.include?('after_exit')
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 test_should_not_run_after_enter_callbacks
493
- assert !@record.callbacks.include?('after_enter')
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
- @before_exit_state_off_callbacks = nil
499
- @before_enter_state_on_callbacks = nil
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