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
data/spec/unit/handlers_spec.rb
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine, 'handlers' do
|
4
|
-
before(:each) {
|
5
|
-
stub_const("DummyLogger", Class.new do
|
6
|
-
attr_reader :result
|
7
|
-
|
8
|
-
def log_error(exception)
|
9
|
-
@result = "log_error(#{exception})"
|
10
|
-
end
|
11
|
-
|
12
|
-
def raise_error
|
13
|
-
raise FiniteMachine::TransitionError
|
14
|
-
end
|
15
|
-
end)
|
16
|
-
}
|
17
|
-
|
18
|
-
it "allows to customise error handling" do
|
19
|
-
called = []
|
20
|
-
fsm = FiniteMachine.new do
|
21
|
-
initial :green
|
22
|
-
|
23
|
-
event :slow, :green => :yellow
|
24
|
-
event :stop, :yellow => :red
|
25
|
-
|
26
|
-
handle FiniteMachine::InvalidStateError do |exception|
|
27
|
-
called << 'invalidstate'
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
expect(fsm.current).to eql(:green)
|
32
|
-
fsm.stop
|
33
|
-
expect(fsm.current).to eql(:green)
|
34
|
-
expect(called).to eql([
|
35
|
-
'invalidstate'
|
36
|
-
])
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'allows for :with to be symbol' do
|
40
|
-
logger = DummyLogger.new
|
41
|
-
fsm = FiniteMachine.new(logger) do
|
42
|
-
initial :green
|
43
|
-
|
44
|
-
event :slow, :green => :yellow
|
45
|
-
event :stop, :yellow => :red
|
46
|
-
|
47
|
-
handle FiniteMachine::InvalidStateError, with: :log_error
|
48
|
-
end
|
49
|
-
|
50
|
-
expect(fsm.current).to eql(:green)
|
51
|
-
fsm.stop
|
52
|
-
expect(fsm.current).to eql(:green)
|
53
|
-
expect(logger.result).to eql('log_error(FiniteMachine::InvalidStateError)')
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'allows for error type as string' do
|
57
|
-
logger = DummyLogger.new
|
58
|
-
called = []
|
59
|
-
fsm = FiniteMachine.new(target: logger) do
|
60
|
-
initial :green
|
61
|
-
|
62
|
-
event :slow, :green => :yellow
|
63
|
-
event :stop, :yellow => :red
|
64
|
-
|
65
|
-
on_enter_yellow do |event|
|
66
|
-
raise_error
|
67
|
-
end
|
68
|
-
|
69
|
-
handle 'InvalidStateError' do |exception|
|
70
|
-
called << 'invalid_state_error'
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
expect(fsm.current).to eql(:green)
|
75
|
-
fsm.stop
|
76
|
-
expect(fsm.current).to eql(:green)
|
77
|
-
expect(called).to eql(['invalid_state_error'])
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'allows for empty block handler' do
|
81
|
-
called = []
|
82
|
-
fsm = FiniteMachine.new do
|
83
|
-
initial :green
|
84
|
-
|
85
|
-
event :slow, :green => :yellow
|
86
|
-
event :stop, :yellow => :red
|
87
|
-
|
88
|
-
handle FiniteMachine::InvalidStateError do
|
89
|
-
called << 'invalidstate'
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
expect(fsm.current).to eql(:green)
|
94
|
-
fsm.stop
|
95
|
-
expect(fsm.current).to eql(:green)
|
96
|
-
expect(called).to eql([
|
97
|
-
'invalidstate'
|
98
|
-
])
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'requires error handler' do
|
102
|
-
expect { FiniteMachine.new do
|
103
|
-
initial :green
|
104
|
-
|
105
|
-
event :slow, :green => :yellow
|
106
|
-
|
107
|
-
handle 'UnknownErrorType'
|
108
|
-
end }.to raise_error(ArgumentError, /error handler/)
|
109
|
-
end
|
110
|
-
|
111
|
-
it 'checks handler class to be Exception' do
|
112
|
-
expect { FiniteMachine.new do
|
113
|
-
initial :green
|
114
|
-
|
115
|
-
event :slow, :green => :yellow
|
116
|
-
|
117
|
-
handle Object do end
|
118
|
-
end }.to raise_error(ArgumentError, /Object isn't an Exception/)
|
119
|
-
end
|
120
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine::HookEvent, '#any_state_or_event' do
|
4
|
-
it "infers default name for state" do
|
5
|
-
hook_event = described_class::Enter
|
6
|
-
expect(described_class.any_state_or_event(hook_event)).to eq(FiniteMachine::ANY_STATE)
|
7
|
-
end
|
8
|
-
|
9
|
-
it "infers default name for event" do
|
10
|
-
hook_event = described_class::Before
|
11
|
-
expect(described_class.any_state_or_event(hook_event)).to eq(FiniteMachine::ANY_EVENT)
|
12
|
-
end
|
13
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine::HookEvent, '#build' do
|
4
|
-
it "builds action event" do
|
5
|
-
hook_event = FiniteMachine::HookEvent::Before.build(:green, :go, :red)
|
6
|
-
expect(hook_event.name).to eq(:go)
|
7
|
-
end
|
8
|
-
|
9
|
-
it "builds state event" do
|
10
|
-
hook_event = FiniteMachine::HookEvent::Enter.build(:green, :go, :red)
|
11
|
-
expect(hook_event.name).to eq(:green)
|
12
|
-
end
|
13
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine::HookEvent, 'eql?' do
|
4
|
-
let(:name) { :green }
|
5
|
-
let(:event_name) { :go }
|
6
|
-
let(:object) { described_class }
|
7
|
-
|
8
|
-
subject(:hook) { object.new(name, event_name, name) }
|
9
|
-
|
10
|
-
context 'with the same object' do
|
11
|
-
let(:other) { hook }
|
12
|
-
|
13
|
-
it "equals" do
|
14
|
-
expect(hook).to eql(other)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'with an equivalent object' do
|
19
|
-
let(:other) { hook.dup }
|
20
|
-
|
21
|
-
it "equals" do
|
22
|
-
expect(hook).to eql(other)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context "with an object having different name" do
|
27
|
-
let(:other_name) { :red }
|
28
|
-
let(:other) { object.new(other_name, event_name, other_name) }
|
29
|
-
|
30
|
-
it "doesn't equal" do
|
31
|
-
expect(hook).not_to eql(other)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine::HookEvent, '#new' do
|
4
|
-
it "reads event name" do
|
5
|
-
hook_event = described_class.new(:green, :go, :green)
|
6
|
-
expect(hook_event.name).to eql(:green)
|
7
|
-
end
|
8
|
-
|
9
|
-
it "reads event type" do
|
10
|
-
hook_event = described_class.new(:green, :go, :green)
|
11
|
-
expect(hook_event.type).to eql(FiniteMachine::HookEvent)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "reads the from state" do
|
15
|
-
hook_event = described_class.new(:green, :go, :red)
|
16
|
-
expect(hook_event.from).to eql(:red)
|
17
|
-
end
|
18
|
-
|
19
|
-
it "freezes object" do
|
20
|
-
hook_event = described_class.new(:green, :go, :green)
|
21
|
-
expect(hook_event.frozen?).to eq(true)
|
22
|
-
end
|
23
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine::HookEvent, '#notify' do
|
4
|
-
it "emits event on the subscriber" do
|
5
|
-
subscriber = spy(:subscriber)
|
6
|
-
hook_event = described_class.new(:green, :go, :red)
|
7
|
-
|
8
|
-
hook_event.notify(subscriber, 1, 2)
|
9
|
-
|
10
|
-
expect(subscriber).to have_received(:emit).with(hook_event, 1, 2)
|
11
|
-
end
|
12
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine::Hooks, '#clear' do
|
4
|
-
it "clears all registered hooks" do
|
5
|
-
hooks = described_class.new
|
6
|
-
|
7
|
-
event_type = FiniteMachine::HookEvent::Before
|
8
|
-
hook = -> { }
|
9
|
-
hooks.register(event_type, :foo, hook)
|
10
|
-
hooks.register(event_type, :bar, hook)
|
11
|
-
|
12
|
-
expect(hooks.empty?).to eq(false)
|
13
|
-
hooks.clear
|
14
|
-
expect(hooks.empty?).to eq(true)
|
15
|
-
end
|
16
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine::Hooks, '#[]' do
|
4
|
-
it "adds and removes a single hook" do
|
5
|
-
hooks = FiniteMachine::Hooks.new
|
6
|
-
expect(hooks).to be_empty
|
7
|
-
|
8
|
-
yielded = []
|
9
|
-
event_type = FiniteMachine::HookEvent::Before
|
10
|
-
hook = -> { }
|
11
|
-
hooks.register(event_type, :foo, hook)
|
12
|
-
|
13
|
-
hooks[event_type][:foo].each do |callback|
|
14
|
-
yielded << callback
|
15
|
-
end
|
16
|
-
|
17
|
-
expect(yielded).to eq([hook])
|
18
|
-
end
|
19
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine::Hooks, '#inspect' do
|
4
|
-
it "displays name and transitions" do
|
5
|
-
hooks = FiniteMachine::Hooks.new
|
6
|
-
hook = -> { }
|
7
|
-
event = FiniteMachine::HookEvent::Enter
|
8
|
-
hooks_map = {event => {yellow: [hook]}}
|
9
|
-
|
10
|
-
hooks.register(event, :yellow, hook)
|
11
|
-
|
12
|
-
expect(hooks.inspect).to eql("<#FiniteMachine::Hooks:0x#{hooks.object_id.to_s(16)} @hooks_map=#{hooks_map}>")
|
13
|
-
end
|
14
|
-
|
15
|
-
it "displays hooks content" do
|
16
|
-
hooks = FiniteMachine::Hooks.new
|
17
|
-
hook = -> { }
|
18
|
-
event = FiniteMachine::HookEvent::Enter
|
19
|
-
hooks_map = {event => {yellow: [hook]}}
|
20
|
-
|
21
|
-
hooks.register(event, :yellow, hook)
|
22
|
-
|
23
|
-
expect(hooks.to_s).to eql(hooks_map.to_s)
|
24
|
-
end
|
25
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine::Hooks, '#register' do
|
4
|
-
it "adds and removes a single hook" do
|
5
|
-
hooks = FiniteMachine::Hooks.new
|
6
|
-
expect(hooks).to be_empty
|
7
|
-
|
8
|
-
event_type = FiniteMachine::HookEvent::Before
|
9
|
-
hook = -> { }
|
10
|
-
|
11
|
-
hooks.register(event_type, :foo, hook)
|
12
|
-
expect(hooks[event_type][:foo]).to eq([hook])
|
13
|
-
|
14
|
-
hooks.unregister(event_type, :foo, hook)
|
15
|
-
expect(hooks[event_type][:foo]).to eq([])
|
16
|
-
end
|
17
|
-
end
|
data/spec/unit/if_unless_spec.rb
DELETED
@@ -1,314 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RSpec.describe FiniteMachine, ':if, :unless' do
|
4
|
-
before(:each) {
|
5
|
-
stub_const("Car", Class.new do
|
6
|
-
attr_accessor :engine_on
|
7
|
-
|
8
|
-
def turn_engine_on
|
9
|
-
@engine_on = true
|
10
|
-
end
|
11
|
-
|
12
|
-
def turn_engine_off
|
13
|
-
@engine_on = false
|
14
|
-
end
|
15
|
-
|
16
|
-
def engine_on?
|
17
|
-
!!@engine_on
|
18
|
-
end
|
19
|
-
end)
|
20
|
-
|
21
|
-
stub_const("Bug", Class.new do
|
22
|
-
def pending?
|
23
|
-
false
|
24
|
-
end
|
25
|
-
end)
|
26
|
-
}
|
27
|
-
|
28
|
-
it "passes context to conditionals" do
|
29
|
-
called = []
|
30
|
-
fsm = FiniteMachine.new do
|
31
|
-
initial :red
|
32
|
-
|
33
|
-
event :go, :red => :green,
|
34
|
-
if: proc { |context| called << "cond_red_green(#{context})"; true}
|
35
|
-
event :stop, from: any_state do
|
36
|
-
choice :red,
|
37
|
-
if: proc { |context| called << "cond_any_red(#{context})"; true }
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
expect(fsm.current).to eq(:red)
|
42
|
-
|
43
|
-
fsm.go
|
44
|
-
expect(fsm.current).to eq(:green)
|
45
|
-
expect(called).to eq(["cond_red_green(#{fsm})"])
|
46
|
-
|
47
|
-
fsm.stop
|
48
|
-
expect(fsm.current).to eq(:red)
|
49
|
-
expect(called).to match_array([
|
50
|
-
"cond_red_green(#{fsm})",
|
51
|
-
"cond_any_red(#{fsm})"
|
52
|
-
])
|
53
|
-
end
|
54
|
-
|
55
|
-
it "passes context & arguments to conditionals" do
|
56
|
-
called = []
|
57
|
-
fsm = FiniteMachine.new do
|
58
|
-
initial :red
|
59
|
-
|
60
|
-
event :go, :red => :green,
|
61
|
-
if: proc { |_, a| called << "cond_red_green(#{a})"; true }
|
62
|
-
event :stop, from: any_state do
|
63
|
-
choice :red,
|
64
|
-
if: proc { |_, b| called << "cond_any_red(#{b})"; true }
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
expect(fsm.current).to eq(:red)
|
69
|
-
|
70
|
-
fsm.go(:foo)
|
71
|
-
expect(fsm.current).to eq(:green)
|
72
|
-
expect(called).to eq(["cond_red_green(foo)"])
|
73
|
-
|
74
|
-
fsm.stop(:bar)
|
75
|
-
expect(fsm.current).to eq(:red)
|
76
|
-
expect(called).to match_array([
|
77
|
-
"cond_red_green(foo)",
|
78
|
-
"cond_any_red(bar)"
|
79
|
-
])
|
80
|
-
end
|
81
|
-
|
82
|
-
it "allows to cancel event with :if option" do
|
83
|
-
called = []
|
84
|
-
|
85
|
-
fsm = FiniteMachine.new do
|
86
|
-
initial :green
|
87
|
-
|
88
|
-
event :slow, :green => :yellow, if: -> { return false }
|
89
|
-
event :stop, :yellow => :red
|
90
|
-
|
91
|
-
# generic callbacks
|
92
|
-
on_enter do |event| called << 'on_enter' end
|
93
|
-
on_transition do |event| called << 'on_transition' end
|
94
|
-
on_exit do |event| called << 'on_exit' end
|
95
|
-
|
96
|
-
# state callbacks
|
97
|
-
on_enter :green do |event| called << 'on_enter_green' end
|
98
|
-
on_enter :yellow do |event| called << "on_enter_yellow" end
|
99
|
-
|
100
|
-
on_transition :green do |event| called << 'on_transition_green' end
|
101
|
-
on_transition :yellow do |event| called << "on_transition_yellow" end
|
102
|
-
|
103
|
-
on_exit :green do |event| called << 'on_exit_green' end
|
104
|
-
on_exit :yellow do |event| called << "on_exit_yellow" end
|
105
|
-
end
|
106
|
-
|
107
|
-
expect(fsm.current).to eql(:green)
|
108
|
-
called = []
|
109
|
-
fsm.slow
|
110
|
-
expect(fsm.current).to eql(:green)
|
111
|
-
expect(called).to eql([])
|
112
|
-
end
|
113
|
-
|
114
|
-
it "allows to cancel event with :unless option" do
|
115
|
-
called = []
|
116
|
-
|
117
|
-
fsm = FiniteMachine.new do
|
118
|
-
initial :green
|
119
|
-
|
120
|
-
event :slow, :green => :yellow, unless: -> { true }
|
121
|
-
event :stop, :yellow => :red
|
122
|
-
|
123
|
-
# generic callbacks
|
124
|
-
on_enter do |event| called << 'on_enter' end
|
125
|
-
on_transition do |event| called << 'on_transition' end
|
126
|
-
on_exit do |event| called << 'on_exit' end
|
127
|
-
|
128
|
-
# state callbacks
|
129
|
-
on_enter :green do |event| called << 'on_enter_green' end
|
130
|
-
on_enter :yellow do |event| called << "on_enter_yellow" end
|
131
|
-
|
132
|
-
on_transition :green do |event| called << 'on_transition_green' end
|
133
|
-
on_transition :yellow do |event| called << "on_transition_yellow" end
|
134
|
-
|
135
|
-
on_exit :green do |event| called << 'on_exit_green' end
|
136
|
-
on_exit :yellow do |event| called << "on_exit_yellow" end
|
137
|
-
end
|
138
|
-
|
139
|
-
expect(fsm.current).to eql(:green)
|
140
|
-
called = []
|
141
|
-
fsm.slow
|
142
|
-
expect(fsm.current).to eql(:green)
|
143
|
-
expect(called).to eql([])
|
144
|
-
end
|
145
|
-
|
146
|
-
it "allows to combine conditionals" do
|
147
|
-
conditions = []
|
148
|
-
|
149
|
-
fsm = FiniteMachine.new do
|
150
|
-
initial :green
|
151
|
-
|
152
|
-
event :slow, :green => :yellow,
|
153
|
-
if: [ -> { conditions << 'first_if'; return true },
|
154
|
-
-> { conditions << 'second_if'; return true}],
|
155
|
-
unless: -> { conditions << 'first_unless'; return true }
|
156
|
-
event :stop, :yellow => :red
|
157
|
-
end
|
158
|
-
|
159
|
-
expect(fsm.current).to eql(:green)
|
160
|
-
fsm.slow
|
161
|
-
expect(fsm.current).to eql(:green)
|
162
|
-
expect(conditions).to eql([
|
163
|
-
'first_if',
|
164
|
-
'second_if',
|
165
|
-
'first_unless'
|
166
|
-
])
|
167
|
-
end
|
168
|
-
|
169
|
-
context 'when proc' do
|
170
|
-
it "specifies :if and :unless" do
|
171
|
-
car = Car.new
|
172
|
-
|
173
|
-
fsm = FiniteMachine.new(car) do
|
174
|
-
initial :neutral
|
175
|
-
|
176
|
-
event :start, :neutral => :one, if: proc {|_car| _car.engine_on? }
|
177
|
-
event :shift, :one => :two
|
178
|
-
end
|
179
|
-
car.turn_engine_off
|
180
|
-
expect(car.engine_on?).to be false
|
181
|
-
expect(fsm.current).to eql(:neutral)
|
182
|
-
fsm.start
|
183
|
-
expect(fsm.current).to eql(:neutral)
|
184
|
-
|
185
|
-
car.turn_engine_on
|
186
|
-
expect(car.engine_on?).to be true
|
187
|
-
expect(fsm.current).to eql(:neutral)
|
188
|
-
fsm.start
|
189
|
-
expect(fsm.current).to eql(:one)
|
190
|
-
end
|
191
|
-
|
192
|
-
it "passes arguments to the scope" do
|
193
|
-
car = Car.new
|
194
|
-
|
195
|
-
fsm = FiniteMachine.new(car) do
|
196
|
-
initial :neutral
|
197
|
-
|
198
|
-
event :start, :neutral => :one, if: proc { |_car, state|
|
199
|
-
_car.engine_on = state
|
200
|
-
_car.engine_on?
|
201
|
-
}
|
202
|
-
event :shift, :one => :two
|
203
|
-
end
|
204
|
-
fsm.start(false)
|
205
|
-
expect(fsm.current).to eql(:neutral)
|
206
|
-
fsm.start(true)
|
207
|
-
expect(fsm.current).to eql(:one)
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
context 'when symbol' do
|
212
|
-
it "specifies :if and :unless" do
|
213
|
-
car = Car.new
|
214
|
-
|
215
|
-
fsm = FiniteMachine.new(car) do
|
216
|
-
initial :neutral
|
217
|
-
|
218
|
-
event :start, :neutral => :one, if: :engine_on?
|
219
|
-
event :shift, :one => :two
|
220
|
-
end
|
221
|
-
car.turn_engine_off
|
222
|
-
expect(car.engine_on?).to be false
|
223
|
-
expect(fsm.current).to eql(:neutral)
|
224
|
-
fsm.start
|
225
|
-
expect(fsm.current).to eql(:neutral)
|
226
|
-
|
227
|
-
car.turn_engine_on
|
228
|
-
expect(car.engine_on?).to be true
|
229
|
-
expect(fsm.current).to eql(:neutral)
|
230
|
-
fsm.start
|
231
|
-
expect(fsm.current).to eql(:one)
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
context 'when string' do
|
236
|
-
it "specifies :if and :unless" do
|
237
|
-
car = Car.new
|
238
|
-
|
239
|
-
fsm = FiniteMachine.new(car) do
|
240
|
-
initial :neutral
|
241
|
-
|
242
|
-
event :start, :neutral => :one, if: "engine_on?"
|
243
|
-
event :shift, :one => :two
|
244
|
-
end
|
245
|
-
car.turn_engine_off
|
246
|
-
expect(car.engine_on?).to be false
|
247
|
-
expect(fsm.current).to eql(:neutral)
|
248
|
-
fsm.start
|
249
|
-
expect(fsm.current).to eql(:neutral)
|
250
|
-
|
251
|
-
car.turn_engine_on
|
252
|
-
expect(car.engine_on?).to be true
|
253
|
-
expect(fsm.current).to eql(:neutral)
|
254
|
-
fsm.start
|
255
|
-
expect(fsm.current).to eql(:one)
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
context 'when same event name' do
|
260
|
-
it "preservers conditions for the same named event" do
|
261
|
-
bug = Bug.new
|
262
|
-
fsm = FiniteMachine.new(bug) do
|
263
|
-
initial :initial
|
264
|
-
|
265
|
-
event :bump, :initial => :low
|
266
|
-
event :bump, :low => :medium, if: :pending?
|
267
|
-
event :bump, :medium => :high
|
268
|
-
end
|
269
|
-
expect(fsm.current).to eq(:initial)
|
270
|
-
fsm.bump
|
271
|
-
expect(fsm.current).to eq(:low)
|
272
|
-
fsm.bump
|
273
|
-
expect(fsm.current).to eq(:low)
|
274
|
-
end
|
275
|
-
|
276
|
-
it "allows for static choice based on branching condition" do
|
277
|
-
fsm = FiniteMachine.new do
|
278
|
-
initial :company_form
|
279
|
-
|
280
|
-
event :next, :company_form => :agreement_form, if: -> { false }
|
281
|
-
event :next, :company_form => :promo_form, if: -> { false }
|
282
|
-
event :next, :company_form => :official_form, if: -> { true }
|
283
|
-
end
|
284
|
-
|
285
|
-
expect(fsm.current).to eq(:company_form)
|
286
|
-
fsm.next
|
287
|
-
expect(fsm.current).to eq(:official_form)
|
288
|
-
end
|
289
|
-
|
290
|
-
it "allows for dynamic choice based on branching condition" do
|
291
|
-
fsm = FiniteMachine.new do
|
292
|
-
initial :company_form
|
293
|
-
|
294
|
-
event :next, :company_form => :agreement_form, if: proc { |_, a| a < 1 }
|
295
|
-
event :next, :company_form => :promo_form, if: proc { |_, a| a == 1 }
|
296
|
-
event :next, :company_form => :official_form, if: proc { |_, a| a > 1 }
|
297
|
-
end
|
298
|
-
expect(fsm.current).to eq(:company_form)
|
299
|
-
|
300
|
-
fsm.next(0)
|
301
|
-
expect(fsm.current).to eq(:agreement_form)
|
302
|
-
fsm.restore!(:company_form)
|
303
|
-
expect(fsm.current).to eq(:company_form)
|
304
|
-
|
305
|
-
fsm.next(1)
|
306
|
-
expect(fsm.current).to eq(:promo_form)
|
307
|
-
fsm.restore!(:company_form)
|
308
|
-
expect(fsm.current).to eq(:company_form)
|
309
|
-
|
310
|
-
fsm.next(2)
|
311
|
-
expect(fsm.current).to eq(:official_form)
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|