finite_machine 0.12.1 → 0.13.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -1
- data/README.md +1 -1
- data/lib/finite_machine.rb +3 -1
- data/lib/finite_machine/choice_merger.rb +2 -2
- data/lib/finite_machine/dsl.rb +4 -4
- data/lib/finite_machine/message_queue.rb +0 -1
- data/lib/finite_machine/state_machine.rb +3 -3
- data/lib/finite_machine/two_phase_lock.rb +6 -6
- data/lib/finite_machine/version.rb +1 -1
- metadata +20 -146
- data/Rakefile +0 -12
- data/benchmarks/memory_profile.rb +0 -11
- data/benchmarks/memory_usage.rb +0 -28
- data/examples/atm.rb +0 -45
- data/examples/bug_system.rb +0 -145
- data/finite_machine.gemspec +0 -30
- data/spec/integration/system_spec.rb +0 -93
- data/spec/performance/benchmark_spec.rb +0 -54
- data/spec/spec_helper.rb +0 -34
- data/spec/unit/alias_target_spec.rb +0 -89
- data/spec/unit/async_callbacks_spec.rb +0 -28
- data/spec/unit/auto_methods_spec.rb +0 -44
- data/spec/unit/callable/call_spec.rb +0 -111
- data/spec/unit/callbacks_spec.rb +0 -851
- data/spec/unit/can_spec.rb +0 -88
- data/spec/unit/cancel_callbacks_spec.rb +0 -46
- data/spec/unit/choice_spec.rb +0 -295
- data/spec/unit/define_spec.rb +0 -55
- data/spec/unit/definition_spec.rb +0 -98
- data/spec/unit/event_names_spec.rb +0 -15
- data/spec/unit/events_map/add_spec.rb +0 -23
- data/spec/unit/events_map/choice_transition_spec.rb +0 -25
- data/spec/unit/events_map/clear_spec.rb +0 -13
- data/spec/unit/events_map/events_spec.rb +0 -16
- data/spec/unit/events_map/inspect_spec.rb +0 -22
- data/spec/unit/events_map/match_transition_spec.rb +0 -35
- data/spec/unit/events_map/move_to_spec.rb +0 -45
- data/spec/unit/events_map/states_for_spec.rb +0 -17
- data/spec/unit/events_spec.rb +0 -390
- data/spec/unit/handlers_spec.rb +0 -120
- data/spec/unit/hook_event/any_state_or_event_spec.rb +0 -13
- data/spec/unit/hook_event/build_spec.rb +0 -13
- data/spec/unit/hook_event/eql_spec.rb +0 -34
- data/spec/unit/hook_event/initialize_spec.rb +0 -23
- data/spec/unit/hook_event/notify_spec.rb +0 -12
- data/spec/unit/hooks/clear_spec.rb +0 -16
- data/spec/unit/hooks/find_spec.rb +0 -19
- data/spec/unit/hooks/inspect_spec.rb +0 -25
- data/spec/unit/hooks/register_spec.rb +0 -17
- data/spec/unit/if_unless_spec.rb +0 -314
- data/spec/unit/initial_spec.rb +0 -190
- data/spec/unit/inspect_spec.rb +0 -22
- data/spec/unit/is_spec.rb +0 -49
- data/spec/unit/log_transitions_spec.rb +0 -24
- data/spec/unit/logger_spec.rb +0 -36
- data/spec/unit/message_queue_spec.rb +0 -62
- data/spec/unit/new_spec.rb +0 -50
- data/spec/unit/respond_to_spec.rb +0 -34
- data/spec/unit/state_parser/parse_spec.rb +0 -56
- data/spec/unit/states_spec.rb +0 -28
- data/spec/unit/subscribers_spec.rb +0 -40
- data/spec/unit/target_spec.rb +0 -225
- data/spec/unit/terminated_spec.rb +0 -85
- data/spec/unit/transition/check_conditions_spec.rb +0 -55
- data/spec/unit/transition/inspect_spec.rb +0 -25
- data/spec/unit/transition/matches_spec.rb +0 -21
- data/spec/unit/transition/states_spec.rb +0 -29
- data/spec/unit/transition/to_state_spec.rb +0 -19
- data/spec/unit/trigger_spec.rb +0 -18
- data/spec/unit/undefined_transition/eql_spec.rb +0 -15
- data/tasks/console.rake +0 -11
- data/tasks/coverage.rake +0 -11
- data/tasks/spec.rake +0 -34
@@ -1,28 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine, 'async callbacks' do
|
4
|
-
it "permits async callback" do
|
5
|
-
called = []
|
6
|
-
fsm = FiniteMachine.new do
|
7
|
-
initial :green, silent: false
|
8
|
-
|
9
|
-
event :slow, :green => :yellow
|
10
|
-
event :go, :yellow => :green
|
11
|
-
|
12
|
-
on_enter :green, :async do |event| called << 'on_enter_green' end
|
13
|
-
on_before :slow, :async do |event| called << 'on_before_slow' end
|
14
|
-
on_exit :yellow, :async do |event| called << 'on_exit_yellow' end
|
15
|
-
on_after :go, :async do |event| called << 'on_after_go' end
|
16
|
-
end
|
17
|
-
fsm.slow
|
18
|
-
fsm.go
|
19
|
-
sleep 0.1
|
20
|
-
expect(called).to match_array([
|
21
|
-
'on_enter_green',
|
22
|
-
'on_before_slow',
|
23
|
-
'on_exit_yellow',
|
24
|
-
'on_enter_green',
|
25
|
-
'on_after_go'
|
26
|
-
])
|
27
|
-
end
|
28
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine, ':auto_methods' do
|
4
|
-
it "allows turning off automatic methods generation" do
|
5
|
-
fsm = FiniteMachine.new(auto_methods: false) do
|
6
|
-
initial :green
|
7
|
-
|
8
|
-
event :slow, :green => :yellow
|
9
|
-
event :stop, :yellow => :red
|
10
|
-
event :ready, :red => :yellow
|
11
|
-
event :go, :yellow => :green
|
12
|
-
|
13
|
-
# allows for fluid callback names
|
14
|
-
once_on_enter_yellow do |event| 'once_on_enter_yellow' end
|
15
|
-
end
|
16
|
-
|
17
|
-
expect(fsm.respond_to?(:slow)).to eq(false)
|
18
|
-
expect { fsm.slow }.to raise_error(NoMethodError)
|
19
|
-
expect(fsm.current).to eq(:green)
|
20
|
-
|
21
|
-
fsm.trigger(:slow)
|
22
|
-
expect(fsm.current).to eq(:yellow)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "allows to use any method name without auto method generation" do
|
26
|
-
fsm = FiniteMachine.new(auto_methods: false) do
|
27
|
-
initial :green
|
28
|
-
|
29
|
-
event :fail, :green => :red
|
30
|
-
end
|
31
|
-
|
32
|
-
fsm.trigger(:fail)
|
33
|
-
expect(fsm.current).to eq(:red)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "detects dangerous event names" do
|
37
|
-
expect {
|
38
|
-
FiniteMachine.new do
|
39
|
-
event :trigger, :a => :b
|
40
|
-
end
|
41
|
-
}.to raise_error(FiniteMachine::AlreadyDefinedError)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
@@ -1,111 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine::Callable, '#call' do
|
4
|
-
|
5
|
-
before(:each) {
|
6
|
-
stub_const("Car", Class.new do
|
7
|
-
attr_reader :result
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@engine_on = false
|
11
|
-
end
|
12
|
-
|
13
|
-
def turn_engine_on
|
14
|
-
@result = 'turn_engine_on'
|
15
|
-
@engine_on = true
|
16
|
-
end
|
17
|
-
|
18
|
-
def set_engine(value = :on)
|
19
|
-
@result = "set_engine(#{value})"
|
20
|
-
@engine = value.to_sym == :on
|
21
|
-
end
|
22
|
-
|
23
|
-
def turn_engine_off
|
24
|
-
@result = 'turn_engine_off'
|
25
|
-
@engine_on = false
|
26
|
-
end
|
27
|
-
|
28
|
-
def engine_on?
|
29
|
-
@result = 'engine_on'
|
30
|
-
!!@engine_on
|
31
|
-
end
|
32
|
-
end)
|
33
|
-
}
|
34
|
-
|
35
|
-
let(:called) { [] }
|
36
|
-
|
37
|
-
let(:target) { Car.new }
|
38
|
-
|
39
|
-
let(:instance) { described_class.new(object) }
|
40
|
-
|
41
|
-
context 'when string' do
|
42
|
-
let(:object) { 'engine_on?' }
|
43
|
-
|
44
|
-
it 'executes method on target' do
|
45
|
-
instance.call(target)
|
46
|
-
expect(target.result).to eql('engine_on')
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
context 'when string' do
|
51
|
-
let(:object) { 'set_engine(:on)' }
|
52
|
-
|
53
|
-
it 'executes method with arguments' do
|
54
|
-
instance.call(target)
|
55
|
-
expect(target.result).to eql('set_engine(on)')
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
context 'when string with arguments' do
|
60
|
-
let(:object) { 'set_engine' }
|
61
|
-
|
62
|
-
it 'executes method with arguments' do
|
63
|
-
instance.call(target, :off)
|
64
|
-
expect(target.result).to eql('set_engine(off)')
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
context 'when symbol' do
|
69
|
-
let(:object) { :set_engine }
|
70
|
-
|
71
|
-
it 'executes method on target' do
|
72
|
-
instance.call(target)
|
73
|
-
expect(target.result).to eql('set_engine(on)')
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
context 'when symbol with arguments' do
|
78
|
-
let(:object) { :set_engine }
|
79
|
-
|
80
|
-
it 'executes method on target' do
|
81
|
-
instance.call(target, :off)
|
82
|
-
expect(target.result).to eql('set_engine(off)')
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
context 'when proc without args' do
|
87
|
-
let(:object) { proc { |a| called << "block_with(#{a})" } }
|
88
|
-
|
89
|
-
it 'passes arguments' do
|
90
|
-
instance.call(target)
|
91
|
-
expect(called).to eql(["block_with(#{target})"])
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
context 'when proc with args' do
|
96
|
-
let(:object) { proc { |a,b| called << "block_with(#{a},#{b})" } }
|
97
|
-
|
98
|
-
it 'passes arguments' do
|
99
|
-
instance.call(target, :red)
|
100
|
-
expect(called).to eql(["block_with(#{target},red)"])
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
context 'when unknown' do
|
105
|
-
let(:object) { Object.new }
|
106
|
-
|
107
|
-
it 'raises error' do
|
108
|
-
expect { instance.call(target) }.to raise_error(ArgumentError)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
data/spec/unit/callbacks_spec.rb
DELETED
@@ -1,851 +0,0 @@
|
|
1
|
-
# frozen_string_literal
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine, 'callbacks' do
|
4
|
-
it "triggers default init event" do
|
5
|
-
called = []
|
6
|
-
fsm = FiniteMachine.new do
|
7
|
-
initial :green, defer: true, silent: false
|
8
|
-
|
9
|
-
# generic state callbacks
|
10
|
-
on_enter do |event| called << 'on_enter' end
|
11
|
-
on_transition do |event| called << 'on_transition' end
|
12
|
-
on_exit do |event| called << 'on_exit' end
|
13
|
-
|
14
|
-
# generic event callbacks
|
15
|
-
on_before any_event do |event| called << 'on_before' end
|
16
|
-
on_after do |event| called << 'on_after' end
|
17
|
-
|
18
|
-
# state callbacks
|
19
|
-
on_enter :none do |event| called << 'on_enter_none' end
|
20
|
-
on_enter :green do |event| called << 'on_enter_green' end
|
21
|
-
|
22
|
-
on_transition :none do |event| called << 'on_transition_none' end
|
23
|
-
on_transition :green do |event| called << 'on_transition_green' end
|
24
|
-
|
25
|
-
on_exit :none do |event| called << 'on_exit_none' end
|
26
|
-
on_exit :green do |event| called << 'on_exit_green' end
|
27
|
-
|
28
|
-
# event callbacks
|
29
|
-
on_before :init do |event| called << 'on_before_init' end
|
30
|
-
on_after :init do |event| called << 'on_after_init' end
|
31
|
-
end
|
32
|
-
|
33
|
-
expect(fsm.current).to eql(:none)
|
34
|
-
fsm.init
|
35
|
-
expect(called).to eql([
|
36
|
-
'on_before',
|
37
|
-
'on_before_init',
|
38
|
-
'on_exit',
|
39
|
-
'on_exit_none',
|
40
|
-
'on_transition',
|
41
|
-
'on_transition_green',
|
42
|
-
'on_enter',
|
43
|
-
'on_enter_green',
|
44
|
-
'on_after',
|
45
|
-
'on_after_init'
|
46
|
-
])
|
47
|
-
end
|
48
|
-
|
49
|
-
it "executes callbacks in order" do
|
50
|
-
called = []
|
51
|
-
fsm = FiniteMachine.new do
|
52
|
-
initial :green, silent: false
|
53
|
-
|
54
|
-
event :slow, :green => :yellow
|
55
|
-
event :stop, :yellow => :red
|
56
|
-
event :ready, :red => :yellow
|
57
|
-
event :go, :yellow => :green
|
58
|
-
|
59
|
-
# generic callbacks
|
60
|
-
on_enter do |event| called << 'on_enter' end
|
61
|
-
on_transition do |event| called << 'on_transition' end
|
62
|
-
on_exit do |event| called << 'on_exit' end
|
63
|
-
|
64
|
-
on_before do |event| called << 'on_before' end
|
65
|
-
on_after do |event| called << 'on_after' end
|
66
|
-
|
67
|
-
# state callbacks
|
68
|
-
on_enter :green do |event| called << 'on_enter_green' end
|
69
|
-
on_enter :yellow do |event| called << "on_enter_yellow" end
|
70
|
-
on_enter :red do |event| called << "on_enter_red" end
|
71
|
-
|
72
|
-
on_transition :green do |event| called << 'on_transition_green' end
|
73
|
-
on_transition :yellow do |event| called << "on_transition_yellow" end
|
74
|
-
on_transition :red do |event| called << "on_transition_red" end
|
75
|
-
|
76
|
-
on_exit :green do |event| called << 'on_exit_green' end
|
77
|
-
on_exit :yellow do |event| called << "on_exit_yellow" end
|
78
|
-
on_exit :red do |event| called << "on_exit_red" end
|
79
|
-
|
80
|
-
# event callbacks
|
81
|
-
on_before :slow do |event| called << 'on_before_slow' end
|
82
|
-
on_before :stop do |event| called << "on_before_stop" end
|
83
|
-
on_before :ready do |event| called << "on_before_ready" end
|
84
|
-
on_before :go do |event| called << "on_before_go" end
|
85
|
-
|
86
|
-
on_after :slow do |event| called << 'on_after_slow' end
|
87
|
-
on_after :stop do |event| called << "on_after_stop" end
|
88
|
-
on_after :ready do |event| called << "on_after_ready" end
|
89
|
-
on_after :go do |event| called << "on_after_go" end
|
90
|
-
end
|
91
|
-
|
92
|
-
expect(fsm.current).to eq(:green)
|
93
|
-
expect(called).to eq([
|
94
|
-
'on_before',
|
95
|
-
'on_exit',
|
96
|
-
'on_transition',
|
97
|
-
'on_transition_green',
|
98
|
-
'on_enter',
|
99
|
-
'on_enter_green',
|
100
|
-
'on_after'
|
101
|
-
])
|
102
|
-
|
103
|
-
called = []
|
104
|
-
fsm.slow
|
105
|
-
expect(called).to eql([
|
106
|
-
'on_before',
|
107
|
-
'on_before_slow',
|
108
|
-
'on_exit',
|
109
|
-
'on_exit_green',
|
110
|
-
'on_transition',
|
111
|
-
'on_transition_yellow',
|
112
|
-
'on_enter',
|
113
|
-
'on_enter_yellow',
|
114
|
-
'on_after',
|
115
|
-
'on_after_slow'
|
116
|
-
])
|
117
|
-
|
118
|
-
called = []
|
119
|
-
fsm.stop
|
120
|
-
expect(called).to eql([
|
121
|
-
'on_before',
|
122
|
-
'on_before_stop',
|
123
|
-
'on_exit',
|
124
|
-
'on_exit_yellow',
|
125
|
-
'on_transition',
|
126
|
-
'on_transition_red',
|
127
|
-
'on_enter',
|
128
|
-
'on_enter_red',
|
129
|
-
'on_after',
|
130
|
-
'on_after_stop'
|
131
|
-
])
|
132
|
-
|
133
|
-
called = []
|
134
|
-
fsm.ready
|
135
|
-
expect(called).to eql([
|
136
|
-
'on_before',
|
137
|
-
'on_before_ready',
|
138
|
-
'on_exit',
|
139
|
-
'on_exit_red',
|
140
|
-
'on_transition',
|
141
|
-
'on_transition_yellow',
|
142
|
-
'on_enter',
|
143
|
-
'on_enter_yellow',
|
144
|
-
'on_after',
|
145
|
-
'on_after_ready'
|
146
|
-
])
|
147
|
-
|
148
|
-
called = []
|
149
|
-
fsm.go
|
150
|
-
expect(called).to eql([
|
151
|
-
'on_before',
|
152
|
-
'on_before_go',
|
153
|
-
'on_exit',
|
154
|
-
'on_exit_yellow',
|
155
|
-
'on_transition',
|
156
|
-
'on_transition_green',
|
157
|
-
'on_enter',
|
158
|
-
'on_enter_green',
|
159
|
-
'on_after',
|
160
|
-
'on_after_go'
|
161
|
-
])
|
162
|
-
end
|
163
|
-
|
164
|
-
it "maintains transition execution sequence from UML statechart" do
|
165
|
-
called = []
|
166
|
-
fsm = FiniteMachine.new do
|
167
|
-
initial :previous, silent: false
|
168
|
-
|
169
|
-
event :go, :previous => :next, if: -> { called << 'guard'; true}
|
170
|
-
|
171
|
-
on_exit { |event| called << "exit_#{event.from}" }
|
172
|
-
on_before { |event| called << "before_#{event.name}" }
|
173
|
-
on_transition { |event| called << "transition_#{event.from}_#{event.to}"}
|
174
|
-
on_enter { |event| called << "enter_#{event.to}"}
|
175
|
-
on_after { |event| called << "after_#{event.name}" }
|
176
|
-
end
|
177
|
-
|
178
|
-
expect(fsm.current).to eq(:previous)
|
179
|
-
fsm.go
|
180
|
-
expect(called).to eq([
|
181
|
-
'before_init',
|
182
|
-
'exit_none',
|
183
|
-
'transition_none_previous',
|
184
|
-
'enter_previous',
|
185
|
-
'after_init',
|
186
|
-
'before_go',
|
187
|
-
'guard',
|
188
|
-
'exit_previous',
|
189
|
-
'transition_previous_next',
|
190
|
-
'enter_next',
|
191
|
-
'after_go'
|
192
|
-
])
|
193
|
-
end
|
194
|
-
|
195
|
-
it "allows multiple callbacks for the same state" do
|
196
|
-
called = []
|
197
|
-
fsm = FiniteMachine.new do
|
198
|
-
initial :green, silent: false
|
199
|
-
|
200
|
-
event :slow, :green => :yellow
|
201
|
-
event :stop, :yellow => :red
|
202
|
-
event :ready, :red => :yellow
|
203
|
-
event :go, :yellow => :green
|
204
|
-
|
205
|
-
# generic state callbacks
|
206
|
-
on_enter do |event| called << 'on_enter' end
|
207
|
-
on_transition do |event| called << 'on_transition' end
|
208
|
-
on_exit do |event| called << 'on_exit' end
|
209
|
-
|
210
|
-
# generic event callbacks
|
211
|
-
on_before do |event| called << 'on_before' end
|
212
|
-
on_after do |event| called << 'on_after' end
|
213
|
-
|
214
|
-
# state callbacks
|
215
|
-
on_exit :green do |event| called << 'on_exit_green_1' end
|
216
|
-
on_exit :green do |event| called << 'on_exit_green_2' end
|
217
|
-
on_enter :yellow do |event| called << 'on_enter_yellow_1' end
|
218
|
-
on_enter :yellow do |event| called << 'on_enter_yellow_2' end
|
219
|
-
on_transition :yellow do |event| called << 'on_transition_yellow_1' end
|
220
|
-
on_transition :yellow do |event| called << 'on_transition_yellow_2' end
|
221
|
-
|
222
|
-
# event callbacks
|
223
|
-
on_before :slow do |event| called << 'on_before_slow_1' end
|
224
|
-
on_before :slow do |event| called << 'on_before_slow_2' end
|
225
|
-
on_after :slow do |event| called << 'on_after_slow_1' end
|
226
|
-
on_after :slow do |event| called << 'on_after_slow_2' end
|
227
|
-
end
|
228
|
-
|
229
|
-
expect(fsm.current).to eql(:green)
|
230
|
-
expect(called).to eql([
|
231
|
-
'on_before',
|
232
|
-
'on_exit',
|
233
|
-
'on_transition',
|
234
|
-
'on_enter',
|
235
|
-
'on_after'
|
236
|
-
])
|
237
|
-
called = []
|
238
|
-
fsm.slow
|
239
|
-
expect(fsm.current).to eql(:yellow)
|
240
|
-
expect(called).to eql([
|
241
|
-
'on_before',
|
242
|
-
'on_before_slow_1',
|
243
|
-
'on_before_slow_2',
|
244
|
-
'on_exit',
|
245
|
-
'on_exit_green_1',
|
246
|
-
'on_exit_green_2',
|
247
|
-
'on_transition',
|
248
|
-
'on_transition_yellow_1',
|
249
|
-
'on_transition_yellow_2',
|
250
|
-
'on_enter',
|
251
|
-
'on_enter_yellow_1',
|
252
|
-
'on_enter_yellow_2',
|
253
|
-
'on_after',
|
254
|
-
'on_after_slow_1',
|
255
|
-
'on_after_slow_2'
|
256
|
-
])
|
257
|
-
end
|
258
|
-
|
259
|
-
it "allows for fluid callback definition" do
|
260
|
-
called = []
|
261
|
-
fsm = FiniteMachine.new do
|
262
|
-
initial :green
|
263
|
-
|
264
|
-
event :slow, :green => :yellow
|
265
|
-
event :stop, :yellow => :red
|
266
|
-
event :ready, :red => :yellow
|
267
|
-
event :go, :yellow => :green
|
268
|
-
|
269
|
-
# state callbacks
|
270
|
-
on_exit_green do |event| called << 'on_exit_green' end
|
271
|
-
on_enter_yellow do |event| called << 'on_enter_yellow' end
|
272
|
-
on_transition_yellow do |event| called << 'on_transition_yellow' end
|
273
|
-
|
274
|
-
# event callbacks
|
275
|
-
on_before_slow do |event| called << 'on_before_slow' end
|
276
|
-
on_after_slow do |event| called << 'on_after_slow' end
|
277
|
-
end
|
278
|
-
|
279
|
-
called = []
|
280
|
-
fsm.slow
|
281
|
-
expect(fsm.current).to eql(:yellow)
|
282
|
-
expect(called).to eql([
|
283
|
-
'on_before_slow',
|
284
|
-
'on_exit_green',
|
285
|
-
'on_transition_yellow',
|
286
|
-
'on_enter_yellow',
|
287
|
-
'on_after_slow'
|
288
|
-
])
|
289
|
-
end
|
290
|
-
|
291
|
-
it "passes event object to callback" do
|
292
|
-
evt = nil
|
293
|
-
fsm = FiniteMachine.new do
|
294
|
-
initial :green
|
295
|
-
|
296
|
-
event :slow, :green => :yellow
|
297
|
-
|
298
|
-
on_enter(:yellow) { |e| evt = e }
|
299
|
-
end
|
300
|
-
|
301
|
-
expect(fsm.current).to eql(:green)
|
302
|
-
fsm.slow
|
303
|
-
expect(fsm.current).to eql(:yellow)
|
304
|
-
|
305
|
-
expect(evt.from).to eql(:green)
|
306
|
-
expect(evt.to).to eql(:yellow)
|
307
|
-
expect(evt.name).to eql(:slow)
|
308
|
-
end
|
309
|
-
|
310
|
-
it "identifies the from state for callback event parameter" do
|
311
|
-
evt = nil
|
312
|
-
fsm = FiniteMachine.new do
|
313
|
-
initial :green
|
314
|
-
|
315
|
-
event :slow, [:red, :blue, :green] => :yellow
|
316
|
-
event :fast, :red => :purple
|
317
|
-
|
318
|
-
on_enter(:yellow) { |e| evt = e }
|
319
|
-
end
|
320
|
-
|
321
|
-
expect(fsm.current).to eql(:green)
|
322
|
-
fsm.slow
|
323
|
-
expect(fsm.current).to eql(:yellow)
|
324
|
-
|
325
|
-
expect(evt.from).to eql(:green)
|
326
|
-
expect(evt.to).to eql(:yellow)
|
327
|
-
expect(evt.name).to eql(:slow)
|
328
|
-
end
|
329
|
-
|
330
|
-
it "passes extra parameters to callbacks" do
|
331
|
-
expected = {name: :init, from: :none, to: :green, a: nil, b: nil, c: nil }
|
332
|
-
|
333
|
-
callback = Proc.new { |event, a, b, c|
|
334
|
-
target.expect(event.from).to target.eql(expected[:from])
|
335
|
-
target.expect(event.to).to target.eql(expected[:to])
|
336
|
-
target.expect(event.name).to target.eql(expected[:name])
|
337
|
-
target.expect(a).to target.eql(expected[:a])
|
338
|
-
target.expect(b).to target.eql(expected[:b])
|
339
|
-
target.expect(c).to target.eql(expected[:c])
|
340
|
-
}
|
341
|
-
|
342
|
-
fsm = FiniteMachine.new(self) do
|
343
|
-
initial :green
|
344
|
-
|
345
|
-
event :slow, :green => :yellow
|
346
|
-
event :stop, :yellow => :red
|
347
|
-
event :ready, :red => :yellow
|
348
|
-
event :go, :yellow => :green
|
349
|
-
|
350
|
-
# generic state callbacks
|
351
|
-
on_enter(&callback)
|
352
|
-
on_transition(&callback)
|
353
|
-
on_exit(&callback)
|
354
|
-
|
355
|
-
# generic event callbacks
|
356
|
-
on_before(&callback)
|
357
|
-
on_after(&callback)
|
358
|
-
|
359
|
-
# state callbacks
|
360
|
-
on_enter :green, &callback
|
361
|
-
on_enter :yellow, &callback
|
362
|
-
on_enter :red, &callback
|
363
|
-
|
364
|
-
on_transition :green , &callback
|
365
|
-
on_transition :yellow, &callback
|
366
|
-
on_transition :red , &callback
|
367
|
-
|
368
|
-
on_exit :green , &callback
|
369
|
-
on_exit :yellow, &callback
|
370
|
-
on_exit :red , &callback
|
371
|
-
|
372
|
-
# event callbacks
|
373
|
-
on_before :slow , &callback
|
374
|
-
on_before :stop , &callback
|
375
|
-
on_before :ready, &callback
|
376
|
-
on_before :go , &callback
|
377
|
-
|
378
|
-
on_after :slow , &callback
|
379
|
-
on_after :stop , &callback
|
380
|
-
on_after :ready, &callback
|
381
|
-
on_after :go , &callback
|
382
|
-
end
|
383
|
-
|
384
|
-
expected = {name: :slow, from: :green, to: :yellow, a: 1, b: 2, c: 3}
|
385
|
-
fsm.slow(1, 2, 3)
|
386
|
-
|
387
|
-
expected = {name: :stop, from: :yellow, to: :red, a: 'foo', b: 'bar'}
|
388
|
-
fsm.stop('foo', 'bar')
|
389
|
-
|
390
|
-
expected = {name: :ready, from: :red, to: :yellow, a: :foo, b: :bar}
|
391
|
-
fsm.ready(:foo, :bar)
|
392
|
-
|
393
|
-
expected = {name: :go, from: :yellow, to: :green, a: nil, b: nil}
|
394
|
-
fsm.go(nil, nil)
|
395
|
-
end
|
396
|
-
|
397
|
-
it "sets callback parameters correctly for transition from :any state" do
|
398
|
-
expected = {name: :init, from: :none, to: :green, a: nil, b: nil, c: nil }
|
399
|
-
|
400
|
-
callback = Proc.new { |event, a, b, c|
|
401
|
-
target.expect(event.from).to target.eql(expected[:from])
|
402
|
-
target.expect(event.to).to target.eql(expected[:to])
|
403
|
-
target.expect(event.name).to target.eql(expected[:name])
|
404
|
-
target.expect(a).to target.eql(expected[:a])
|
405
|
-
target.expect(b).to target.eql(expected[:b])
|
406
|
-
target.expect(c).to target.eql(expected[:c])
|
407
|
-
}
|
408
|
-
|
409
|
-
fsm = FiniteMachine.new(self) do
|
410
|
-
initial :red
|
411
|
-
|
412
|
-
event :power_on, :off => :red
|
413
|
-
event :power_off, any_state => :off
|
414
|
-
event :go, :red => :green
|
415
|
-
event :slow, :green => :yellow
|
416
|
-
event :stop, :yellow => :red
|
417
|
-
|
418
|
-
# generic state callbacks
|
419
|
-
on_enter(&callback)
|
420
|
-
on_transition(&callback)
|
421
|
-
on_exit(&callback)
|
422
|
-
|
423
|
-
# generic event callbacks
|
424
|
-
on_before(&callback)
|
425
|
-
on_after(&callback)
|
426
|
-
|
427
|
-
# state callbacks
|
428
|
-
on_enter :green, &callback
|
429
|
-
on_enter :yellow, &callback
|
430
|
-
on_enter :red, &callback
|
431
|
-
on_enter :off, &callback
|
432
|
-
on_enter :off, &callback
|
433
|
-
|
434
|
-
on_transition :green, &callback
|
435
|
-
on_transition :yellow, &callback
|
436
|
-
on_transition :red, &callback
|
437
|
-
on_transition :off, &callback
|
438
|
-
on_transition :off, &callback
|
439
|
-
|
440
|
-
on_exit :green, &callback
|
441
|
-
on_exit :yellow, &callback
|
442
|
-
on_exit :red, &callback
|
443
|
-
on_exit :off, &callback
|
444
|
-
on_exit :off, &callback
|
445
|
-
|
446
|
-
# event callbacks
|
447
|
-
on_before :power_on, &callback
|
448
|
-
on_before :power_off, &callback
|
449
|
-
on_before :go, &callback
|
450
|
-
on_before :slow, &callback
|
451
|
-
on_before :stop, &callback
|
452
|
-
|
453
|
-
on_after :power_on, &callback
|
454
|
-
on_after :power_off, &callback
|
455
|
-
on_after :go, &callback
|
456
|
-
on_after :slow, &callback
|
457
|
-
on_after :stop, &callback
|
458
|
-
end
|
459
|
-
|
460
|
-
expect(fsm.current).to eq(:red)
|
461
|
-
|
462
|
-
expected = {name: :go, from: :red, to: :green, a: 1, b: 2, c: 3 }
|
463
|
-
fsm.go(1, 2, 3)
|
464
|
-
|
465
|
-
expected = {name: :slow, from: :green, to: :yellow, a: 4, b: 5, c: 6}
|
466
|
-
fsm.slow(4, 5, 6)
|
467
|
-
|
468
|
-
expected = {name: :stop, from: :yellow, to: :red, a: 7, b: 8, c: 9}
|
469
|
-
fsm.stop(7, 8, 9)
|
470
|
-
|
471
|
-
expected = {name: :power_off, from: :red, to: :off, a: 10, b: 11, c: 12}
|
472
|
-
fsm.power_off(10, 11, 12)
|
473
|
-
end
|
474
|
-
|
475
|
-
it "raises an error with invalid callback name" do
|
476
|
-
expect {
|
477
|
-
FiniteMachine.new do
|
478
|
-
initial :green
|
479
|
-
|
480
|
-
event :slow, :green => :yellow
|
481
|
-
|
482
|
-
on_enter(:magic) { |event| called << 'on_enter'}
|
483
|
-
end
|
484
|
-
}.to raise_error(FiniteMachine::InvalidCallbackNameError, /\"magic\" is not a valid callback name/)
|
485
|
-
end
|
486
|
-
|
487
|
-
it "doesn't allow to mix state callback with event name" do
|
488
|
-
expect {
|
489
|
-
FiniteMachine.new do
|
490
|
-
event :slow, :green => :yellow
|
491
|
-
|
492
|
-
on_enter_slow do |event| end
|
493
|
-
end
|
494
|
-
}.to raise_error(FiniteMachine::InvalidCallbackNameError, "\"on_enter\" callback is a state listener and cannot be used with \"slow\" event name. Please use on_before or on_after instead.")
|
495
|
-
end
|
496
|
-
|
497
|
-
it "doesn't allow to mix event callback with state name" do
|
498
|
-
expect {
|
499
|
-
FiniteMachine.new do
|
500
|
-
event :slow, :green => :yellow
|
501
|
-
|
502
|
-
on_before_green do |event| end
|
503
|
-
end
|
504
|
-
}.to raise_error(FiniteMachine::InvalidCallbackNameError, '"on_before" callback is an event listener and cannot be used with "green" state name. Please use on_enter, on_transition or on_exit instead.')
|
505
|
-
end
|
506
|
-
|
507
|
-
it "propagates exceptions raised inside callback" do
|
508
|
-
fsm = FiniteMachine.new do
|
509
|
-
initial :green
|
510
|
-
|
511
|
-
event :slow, :green => :yellow
|
512
|
-
|
513
|
-
on_enter(:yellow) { raise RuntimeError }
|
514
|
-
end
|
515
|
-
|
516
|
-
expect(fsm.current).to eql(:green)
|
517
|
-
expect { fsm.slow }.to raise_error(RuntimeError)
|
518
|
-
end
|
519
|
-
|
520
|
-
it "executes callbacks with multiple 'from' transitions" do
|
521
|
-
called = []
|
522
|
-
fsm = FiniteMachine.new do
|
523
|
-
initial :green
|
524
|
-
|
525
|
-
event :stop, :green => :yellow
|
526
|
-
event :stop, :yellow => :red
|
527
|
-
|
528
|
-
on_before_stop do |event|
|
529
|
-
called << 'on_before_stop'
|
530
|
-
end
|
531
|
-
end
|
532
|
-
expect(fsm.current).to eql(:green)
|
533
|
-
fsm.stop
|
534
|
-
expect(fsm.current).to eql(:yellow)
|
535
|
-
fsm.stop
|
536
|
-
expect(fsm.current).to eql(:red)
|
537
|
-
expect(called).to eql([
|
538
|
-
'on_before_stop',
|
539
|
-
'on_before_stop'
|
540
|
-
])
|
541
|
-
end
|
542
|
-
|
543
|
-
it "allows to define callbacks on machine instance" do
|
544
|
-
called = []
|
545
|
-
fsm = FiniteMachine.new do
|
546
|
-
initial :green
|
547
|
-
|
548
|
-
event :slow, :green => :yellow
|
549
|
-
event :stop, :yellow => :red
|
550
|
-
event :ready, :red => :yellow
|
551
|
-
event :go, :yellow => :green
|
552
|
-
end
|
553
|
-
|
554
|
-
fsm.on_enter_yellow do |event|
|
555
|
-
called << 'on_enter_yellow'
|
556
|
-
end
|
557
|
-
|
558
|
-
expect(fsm.current).to eql(:green)
|
559
|
-
fsm.slow
|
560
|
-
expect(called).to eql([
|
561
|
-
'on_enter_yellow'
|
562
|
-
])
|
563
|
-
end
|
564
|
-
|
565
|
-
it "raises error for unknown callback" do
|
566
|
-
expect {
|
567
|
-
FiniteMachine.new do
|
568
|
-
initial :green
|
569
|
-
|
570
|
-
event :slow, :green => :yellow
|
571
|
-
event :stop, :yellow => :red
|
572
|
-
event :ready, :red => :yellow
|
573
|
-
event :go, :yellow => :green
|
574
|
-
|
575
|
-
on_enter_unknown do |event| end
|
576
|
-
end
|
577
|
-
}.to raise_error(NameError, /`on_enter_unknown'/)
|
578
|
-
end
|
579
|
-
|
580
|
-
it "triggers callbacks only once" do
|
581
|
-
called = []
|
582
|
-
fsm = FiniteMachine.new do
|
583
|
-
initial :green, silent: false
|
584
|
-
|
585
|
-
event :slow, :green => :yellow
|
586
|
-
event :go, :yellow => :green
|
587
|
-
|
588
|
-
# state callbacks
|
589
|
-
once_on_enter_green do |event| called << 'once_on_enter_green' end
|
590
|
-
once_on_enter_yellow do |event| called << 'once_on_enter_yellow' end
|
591
|
-
|
592
|
-
once_on_transition_green do |event| called << 'once_on_transition_green' end
|
593
|
-
once_on_transition_yellow do |event| called << 'once_on_transition_yellow' end
|
594
|
-
once_on_exit_none do |event| called << 'once_on_exit_none' end
|
595
|
-
once_on_exit_green do |event| called << 'once_on_exit_green' end
|
596
|
-
once_on_exit_yellow do |event| called << 'once_on_exit_yellow' end
|
597
|
-
|
598
|
-
# event callbacks
|
599
|
-
once_on_before_init do |event| called << 'once_on_before_init' end
|
600
|
-
once_on_before_slow do |event| called << 'once_on_before_slow' end
|
601
|
-
once_on_before_go do |event| called << 'once_on_before_go' end
|
602
|
-
|
603
|
-
once_on_after_init do |event| called << 'once_on_after_init' end
|
604
|
-
once_on_after_slow do |event| called << 'once_on_after_slow' end
|
605
|
-
once_on_after_go do |event| called << 'once_on_after_go' end
|
606
|
-
end
|
607
|
-
expect(fsm.current).to eql(:green)
|
608
|
-
fsm.slow
|
609
|
-
expect(fsm.current).to eql(:yellow)
|
610
|
-
fsm.go
|
611
|
-
expect(fsm.current).to eql(:green)
|
612
|
-
fsm.slow
|
613
|
-
expect(fsm.current).to eql(:yellow)
|
614
|
-
expect(called).to eql([
|
615
|
-
'once_on_before_init',
|
616
|
-
'once_on_exit_none',
|
617
|
-
'once_on_transition_green',
|
618
|
-
'once_on_enter_green',
|
619
|
-
'once_on_after_init',
|
620
|
-
'once_on_before_slow',
|
621
|
-
'once_on_exit_green',
|
622
|
-
'once_on_transition_yellow',
|
623
|
-
'once_on_enter_yellow',
|
624
|
-
'once_on_after_slow',
|
625
|
-
'once_on_before_go',
|
626
|
-
'once_on_exit_yellow',
|
627
|
-
'once_on_after_go'
|
628
|
-
])
|
629
|
-
end
|
630
|
-
|
631
|
-
xit "groups callbacks"
|
632
|
-
|
633
|
-
it "groups states from separate events with the same name" do
|
634
|
-
callbacks = []
|
635
|
-
fsm = FiniteMachine.new do
|
636
|
-
initial :initial, silent: false
|
637
|
-
|
638
|
-
event :bump, :initial => :low
|
639
|
-
event :bump, :low => :medium
|
640
|
-
event :bump, :medium => :high
|
641
|
-
|
642
|
-
on_enter do |event|
|
643
|
-
callbacks << "enter_#{event.name}_#{event.from}_#{event.to}"
|
644
|
-
end
|
645
|
-
on_exit do |event|
|
646
|
-
callbacks << "exit_#{event.name}_#{event.from}_#{event.to}"
|
647
|
-
end
|
648
|
-
on_before do |event|
|
649
|
-
callbacks << "before_#{event.name}_#{event.from}_#{event.to}"
|
650
|
-
end
|
651
|
-
on_after do |event|
|
652
|
-
callbacks << "after_#{event.name}_#{event.from}_#{event.to}"
|
653
|
-
end
|
654
|
-
end
|
655
|
-
|
656
|
-
expect(fsm.current).to eq(:initial)
|
657
|
-
fsm.bump
|
658
|
-
expect(callbacks).to eq([
|
659
|
-
'before_init_none_initial',
|
660
|
-
'exit_init_none_initial',
|
661
|
-
'enter_init_none_initial',
|
662
|
-
'after_init_none_initial',
|
663
|
-
'before_bump_initial_low',
|
664
|
-
'exit_bump_initial_low',
|
665
|
-
'enter_bump_initial_low',
|
666
|
-
'after_bump_initial_low'
|
667
|
-
])
|
668
|
-
fsm.bump
|
669
|
-
expect(callbacks).to eq([
|
670
|
-
'before_init_none_initial',
|
671
|
-
'exit_init_none_initial',
|
672
|
-
'enter_init_none_initial',
|
673
|
-
'after_init_none_initial',
|
674
|
-
'before_bump_initial_low',
|
675
|
-
'exit_bump_initial_low',
|
676
|
-
'enter_bump_initial_low',
|
677
|
-
'after_bump_initial_low',
|
678
|
-
'before_bump_low_medium',
|
679
|
-
'exit_bump_low_medium',
|
680
|
-
'enter_bump_low_medium',
|
681
|
-
'after_bump_low_medium'
|
682
|
-
])
|
683
|
-
fsm.bump
|
684
|
-
expect(callbacks).to eq([
|
685
|
-
'before_init_none_initial',
|
686
|
-
'exit_init_none_initial',
|
687
|
-
'enter_init_none_initial',
|
688
|
-
'after_init_none_initial',
|
689
|
-
'before_bump_initial_low',
|
690
|
-
'exit_bump_initial_low',
|
691
|
-
'enter_bump_initial_low',
|
692
|
-
'after_bump_initial_low',
|
693
|
-
'before_bump_low_medium',
|
694
|
-
'exit_bump_low_medium',
|
695
|
-
'enter_bump_low_medium',
|
696
|
-
'after_bump_low_medium',
|
697
|
-
'before_bump_medium_high',
|
698
|
-
'exit_bump_medium_high',
|
699
|
-
'enter_bump_medium_high',
|
700
|
-
'after_bump_medium_high'
|
701
|
-
])
|
702
|
-
end
|
703
|
-
|
704
|
-
it "groups states under event name" do
|
705
|
-
callbacks = []
|
706
|
-
fsm = FiniteMachine.new do
|
707
|
-
initial :initial, silent: false
|
708
|
-
|
709
|
-
event :bump, :initial => :low,
|
710
|
-
:low => :medium,
|
711
|
-
:medium => :high
|
712
|
-
|
713
|
-
on_enter do |event|
|
714
|
-
callbacks << "enter_#{event.name}_#{event.from}_#{event.to}"
|
715
|
-
end
|
716
|
-
on_before do |event|
|
717
|
-
callbacks << "before_#{event.name}_#{event.from}_#{event.to}"
|
718
|
-
end
|
719
|
-
end
|
720
|
-
|
721
|
-
expect(fsm.current).to eq(:initial)
|
722
|
-
fsm.bump
|
723
|
-
expect(callbacks).to eq([
|
724
|
-
'before_init_none_initial',
|
725
|
-
'enter_init_none_initial',
|
726
|
-
'before_bump_initial_low',
|
727
|
-
'enter_bump_initial_low'
|
728
|
-
])
|
729
|
-
fsm.bump
|
730
|
-
expect(callbacks).to eq([
|
731
|
-
'before_init_none_initial',
|
732
|
-
'enter_init_none_initial',
|
733
|
-
'before_bump_initial_low',
|
734
|
-
'enter_bump_initial_low',
|
735
|
-
'before_bump_low_medium',
|
736
|
-
'enter_bump_low_medium'
|
737
|
-
])
|
738
|
-
fsm.bump
|
739
|
-
expect(callbacks).to eq([
|
740
|
-
'before_init_none_initial',
|
741
|
-
'enter_init_none_initial',
|
742
|
-
'before_bump_initial_low',
|
743
|
-
'enter_bump_initial_low',
|
744
|
-
'before_bump_low_medium',
|
745
|
-
'enter_bump_low_medium',
|
746
|
-
'before_bump_medium_high',
|
747
|
-
'enter_bump_medium_high'
|
748
|
-
])
|
749
|
-
end
|
750
|
-
|
751
|
-
it "permits state and event with the same name" do
|
752
|
-
called = []
|
753
|
-
fsm = FiniteMachine.new do
|
754
|
-
initial :on_hook, silent: false
|
755
|
-
|
756
|
-
event :off_hook, :on_hook => :off_hook
|
757
|
-
event :on_hook, :off_hook => :on_hook
|
758
|
-
|
759
|
-
on_before(:on_hook) { |event| called << "on_before_#{event.name}"}
|
760
|
-
on_enter(:on_hook) { |event| called << "on_enter_#{event.to}"}
|
761
|
-
end
|
762
|
-
expect(fsm.current).to eq(:on_hook)
|
763
|
-
expect(called).to eq([
|
764
|
-
'on_enter_on_hook'
|
765
|
-
])
|
766
|
-
fsm.off_hook
|
767
|
-
expect(fsm.current).to eq(:off_hook)
|
768
|
-
fsm.on_hook
|
769
|
-
expect(called).to eq([
|
770
|
-
'on_enter_on_hook',
|
771
|
-
'on_before_on_hook',
|
772
|
-
'on_enter_on_hook'
|
773
|
-
]);
|
774
|
-
end
|
775
|
-
|
776
|
-
it "allows to selectively silence events" do
|
777
|
-
called = []
|
778
|
-
fsm = FiniteMachine.new do
|
779
|
-
initial :yellow
|
780
|
-
|
781
|
-
event :go, :yellow => :green, silent: true
|
782
|
-
event :stop, :green => :red
|
783
|
-
|
784
|
-
on_enter :green do |event| called << 'on_enter_yellow' end
|
785
|
-
on_enter :red do |event| called << 'on_enter_red' end
|
786
|
-
end
|
787
|
-
expect(fsm.current).to eq(:yellow)
|
788
|
-
fsm.go
|
789
|
-
fsm.stop
|
790
|
-
expect(called).to eq(['on_enter_red'])
|
791
|
-
end
|
792
|
-
|
793
|
-
it "executes event-based callbacks even when state does not change" do
|
794
|
-
called = []
|
795
|
-
fsm = FiniteMachine.new do
|
796
|
-
initial :active
|
797
|
-
|
798
|
-
event :advance, :active => :inactive, if: -> { false }
|
799
|
-
event :advance, :inactive => :active, if: -> { false }
|
800
|
-
|
801
|
-
on_before do |event|
|
802
|
-
called << "before_#{event.name}_#{event.from}_#{event.to}"
|
803
|
-
end
|
804
|
-
on_after do |event|
|
805
|
-
called << "after_#{event.name}_#{event.from}_#{event.to}"
|
806
|
-
end
|
807
|
-
end
|
808
|
-
expect(fsm.current).to eq(:active)
|
809
|
-
fsm.advance
|
810
|
-
expect(fsm.current).to eq(:active)
|
811
|
-
expect(called).to eq([
|
812
|
-
'before_advance_active_inactive',
|
813
|
-
'after_advance_active_inactive'
|
814
|
-
])
|
815
|
-
end
|
816
|
-
|
817
|
-
it "doesn't transition if error raised in callback" do
|
818
|
-
fsm = FiniteMachine.new do
|
819
|
-
initial :green
|
820
|
-
|
821
|
-
event :slow, :green => :yellow
|
822
|
-
|
823
|
-
on_enter { raise RuntimeError }
|
824
|
-
end
|
825
|
-
|
826
|
-
expect {
|
827
|
-
fsm.slow
|
828
|
-
}.to raise_error(RuntimeError)
|
829
|
-
expect(fsm.current).to eq(:green)
|
830
|
-
end
|
831
|
-
|
832
|
-
xit "narrows down on_transition callback to state transition" do
|
833
|
-
called = []
|
834
|
-
fsm = FiniteMachine.new do
|
835
|
-
initial :red
|
836
|
-
|
837
|
-
event :ready, :red => :yellow
|
838
|
-
event :go, :yellow => :green
|
839
|
-
event :stop, :green => :red
|
840
|
-
|
841
|
-
on_transition :yellow => :green do
|
842
|
-
called << 'on_transition_yellow_green'
|
843
|
-
end
|
844
|
-
end
|
845
|
-
|
846
|
-
fsm.ready
|
847
|
-
fsm.go
|
848
|
-
|
849
|
-
expect(called).to eq(['on_transition_yellow_green'])
|
850
|
-
end
|
851
|
-
end
|