finite_machine 0.11.2 → 0.14.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.
Files changed (101) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +80 -0
  3. data/LICENSE.txt +1 -1
  4. data/README.md +679 -624
  5. data/lib/finite_machine.rb +35 -45
  6. data/lib/finite_machine/async_call.rb +5 -21
  7. data/lib/finite_machine/callable.rb +4 -4
  8. data/lib/finite_machine/catchable.rb +24 -14
  9. data/lib/finite_machine/choice_merger.rb +20 -20
  10. data/lib/finite_machine/const.rb +16 -0
  11. data/lib/finite_machine/definition.rb +3 -3
  12. data/lib/finite_machine/dsl.rb +98 -151
  13. data/lib/finite_machine/env.rb +4 -2
  14. data/lib/finite_machine/event_definition.rb +7 -15
  15. data/lib/finite_machine/{events_chain.rb → events_map.rb} +40 -53
  16. data/lib/finite_machine/hook_event.rb +60 -61
  17. data/lib/finite_machine/hooks.rb +44 -36
  18. data/lib/finite_machine/listener.rb +2 -2
  19. data/lib/finite_machine/logger.rb +5 -4
  20. data/lib/finite_machine/{event_queue.rb → message_queue.rb} +76 -32
  21. data/lib/finite_machine/observer.rb +71 -34
  22. data/lib/finite_machine/safety.rb +16 -14
  23. data/lib/finite_machine/state_definition.rb +3 -5
  24. data/lib/finite_machine/state_machine.rb +93 -76
  25. data/lib/finite_machine/state_parser.rb +55 -83
  26. data/lib/finite_machine/subscribers.rb +2 -2
  27. data/lib/finite_machine/threadable.rb +3 -1
  28. data/lib/finite_machine/transition.rb +34 -34
  29. data/lib/finite_machine/transition_builder.rb +23 -32
  30. data/lib/finite_machine/transition_event.rb +12 -11
  31. data/lib/finite_machine/two_phase_lock.rb +8 -6
  32. data/lib/finite_machine/undefined_transition.rb +5 -6
  33. data/lib/finite_machine/version.rb +2 -2
  34. metadata +58 -142
  35. data/.gitignore +0 -18
  36. data/.rspec +0 -5
  37. data/.ruby-gemset +0 -1
  38. data/.ruby-version +0 -1
  39. data/.travis.yml +0 -26
  40. data/Gemfile +0 -15
  41. data/Rakefile +0 -8
  42. data/assets/finite_machine_logo.png +0 -0
  43. data/examples/atm.rb +0 -45
  44. data/examples/bug_system.rb +0 -145
  45. data/finite_machine.gemspec +0 -23
  46. data/lib/finite_machine/async_proxy.rb +0 -30
  47. data/spec/integration/system_spec.rb +0 -95
  48. data/spec/spec_helper.rb +0 -33
  49. data/spec/unit/alias_target_spec.rb +0 -108
  50. data/spec/unit/async_events_spec.rb +0 -138
  51. data/spec/unit/callable/call_spec.rb +0 -113
  52. data/spec/unit/callbacks_spec.rb +0 -942
  53. data/spec/unit/can_spec.rb +0 -98
  54. data/spec/unit/choice_spec.rb +0 -331
  55. data/spec/unit/define_spec.rb +0 -55
  56. data/spec/unit/definition_spec.rb +0 -115
  57. data/spec/unit/event_names_spec.rb +0 -19
  58. data/spec/unit/event_queue_spec.rb +0 -52
  59. data/spec/unit/events_chain/add_spec.rb +0 -25
  60. data/spec/unit/events_chain/cancel_transitions_spec.rb +0 -22
  61. data/spec/unit/events_chain/choice_transition_spec.rb +0 -28
  62. data/spec/unit/events_chain/clear_spec.rb +0 -15
  63. data/spec/unit/events_chain/events_spec.rb +0 -18
  64. data/spec/unit/events_chain/inspect_spec.rb +0 -24
  65. data/spec/unit/events_chain/match_transition_spec.rb +0 -37
  66. data/spec/unit/events_chain/move_to_spec.rb +0 -48
  67. data/spec/unit/events_chain/states_for_spec.rb +0 -17
  68. data/spec/unit/events_spec.rb +0 -459
  69. data/spec/unit/handlers_spec.rb +0 -152
  70. data/spec/unit/hook_event/build_spec.rb +0 -15
  71. data/spec/unit/hook_event/eql_spec.rb +0 -36
  72. data/spec/unit/hook_event/infer_default_name_spec.rb +0 -13
  73. data/spec/unit/hook_event/initialize_spec.rb +0 -25
  74. data/spec/unit/hook_event/notify_spec.rb +0 -14
  75. data/spec/unit/hooks/call_spec.rb +0 -24
  76. data/spec/unit/hooks/clear_spec.rb +0 -16
  77. data/spec/unit/hooks/inspect_spec.rb +0 -17
  78. data/spec/unit/hooks/register_spec.rb +0 -22
  79. data/spec/unit/if_unless_spec.rb +0 -353
  80. data/spec/unit/initial_spec.rb +0 -222
  81. data/spec/unit/inspect_spec.rb +0 -17
  82. data/spec/unit/is_spec.rb +0 -55
  83. data/spec/unit/log_transitions_spec.rb +0 -30
  84. data/spec/unit/logger_spec.rb +0 -38
  85. data/spec/unit/respond_to_spec.rb +0 -38
  86. data/spec/unit/state_parser/inspect_spec.rb +0 -25
  87. data/spec/unit/state_parser/parse_spec.rb +0 -59
  88. data/spec/unit/states_spec.rb +0 -34
  89. data/spec/unit/subscribers_spec.rb +0 -42
  90. data/spec/unit/target_spec.rb +0 -225
  91. data/spec/unit/terminated_spec.rb +0 -95
  92. data/spec/unit/transition/check_conditions_spec.rb +0 -54
  93. data/spec/unit/transition/inspect_spec.rb +0 -25
  94. data/spec/unit/transition/matches_spec.rb +0 -23
  95. data/spec/unit/transition/states_spec.rb +0 -31
  96. data/spec/unit/transition/to_state_spec.rb +0 -27
  97. data/spec/unit/trigger_spec.rb +0 -22
  98. data/spec/unit/undefined_transition/eql_spec.rb +0 -17
  99. data/tasks/console.rake +0 -11
  100. data/tasks/coverage.rake +0 -11
  101. data/tasks/spec.rake +0 -29
@@ -1,152 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe FiniteMachine, 'handlers' do
6
-
7
- before(:each) {
8
- stub_const("DummyLogger", Class.new do
9
- attr_reader :result
10
-
11
- def log_error(exception)
12
- @result = "log_error(#{exception})"
13
- end
14
-
15
- def raise_error
16
- raise FiniteMachine::TransitionError
17
- end
18
- end)
19
- }
20
-
21
- it "allows to customise error handling" do
22
- called = []
23
- fsm = FiniteMachine.define do
24
- initial :green
25
-
26
- events {
27
- event :slow, :green => :yellow
28
- event :stop, :yellow => :red
29
- }
30
-
31
- handlers {
32
- handle FiniteMachine::InvalidStateError do |exception|
33
- called << 'invalidstate'
34
- end
35
- }
36
- end
37
-
38
- expect(fsm.current).to eql(:green)
39
- fsm.stop
40
- expect(fsm.current).to eql(:green)
41
- expect(called).to eql([
42
- 'invalidstate'
43
- ])
44
- end
45
-
46
- it 'allows for :with to be symbol' do
47
- logger = DummyLogger.new
48
- fsm = FiniteMachine.define do
49
- initial :green
50
-
51
- target logger
52
-
53
- events {
54
- event :slow, :green => :yellow
55
- event :stop, :yellow => :red
56
- }
57
-
58
- handlers {
59
- handle FiniteMachine::InvalidStateError, with: :log_error
60
- }
61
- end
62
-
63
- expect(fsm.current).to eql(:green)
64
- fsm.stop
65
- expect(fsm.current).to eql(:green)
66
- expect(logger.result).to eql('log_error(FiniteMachine::InvalidStateError)')
67
- end
68
-
69
- it 'allows for error type as string' do
70
- logger = DummyLogger.new
71
- called = []
72
- fsm = FiniteMachine.define do
73
- initial :green
74
-
75
- target logger
76
-
77
- events {
78
- event :slow, :green => :yellow
79
- event :stop, :yellow => :red
80
- }
81
-
82
- callbacks {
83
- on_enter_yellow do |event|
84
- raise_error
85
- end
86
- }
87
- handlers {
88
- handle 'InvalidStateError' do |exception|
89
- called << 'invalid_state_error'
90
- end
91
- }
92
- end
93
-
94
- expect(fsm.current).to eql(:green)
95
- fsm.stop
96
- expect(fsm.current).to eql(:green)
97
- expect(called).to eql(['invalid_state_error'])
98
- end
99
-
100
- it 'allows for empty block handler' do
101
- called = []
102
- fsm = FiniteMachine.define do
103
- initial :green
104
-
105
- events {
106
- event :slow, :green => :yellow
107
- event :stop, :yellow => :red
108
- }
109
-
110
- handlers {
111
- handle FiniteMachine::InvalidStateError do
112
- called << 'invalidstate'
113
- end
114
- }
115
- end
116
-
117
- expect(fsm.current).to eql(:green)
118
- fsm.stop
119
- expect(fsm.current).to eql(:green)
120
- expect(called).to eql([
121
- 'invalidstate'
122
- ])
123
- end
124
-
125
- it 'requires error handler' do
126
- expect { FiniteMachine.define do
127
- initial :green
128
-
129
- events {
130
- event :slow, :green => :yellow
131
- }
132
-
133
- handlers {
134
- handle 'UnknownErrorType'
135
- }
136
- end }.to raise_error(ArgumentError, /error handler/)
137
- end
138
-
139
- it 'checks handler class to be Exception' do
140
- expect { FiniteMachine.define do
141
- initial :green
142
-
143
- events {
144
- event :slow, :green => :yellow
145
- }
146
-
147
- handlers {
148
- handle Object do end
149
- }
150
- end }.to raise_error(ArgumentError, /Object isn't an Exception/)
151
- end
152
- end
@@ -1,15 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe FiniteMachine::HookEvent, '#build' do
6
- it "builds action event" do
7
- hook_event = FiniteMachine::HookEvent::Before.build(:green, :go, :red)
8
- expect(hook_event.name).to eq(:go)
9
- end
10
-
11
- it "builds state event" do
12
- hook_event = FiniteMachine::HookEvent::Enter.build(:green, :go, :red)
13
- expect(hook_event.name).to eq(:green)
14
- end
15
- end
@@ -1,36 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe FiniteMachine::HookEvent, 'eql?' do
6
- let(:name) { :green }
7
- let(:event_name) { :go }
8
- let(:object) { described_class }
9
-
10
- subject(:hook) { object.new(name, event_name, name) }
11
-
12
- context 'with the same object' do
13
- let(:other) { hook }
14
-
15
- it "equals" do
16
- expect(hook).to eql(other)
17
- end
18
- end
19
-
20
- context 'with an equivalent object' do
21
- let(:other) { hook.dup }
22
-
23
- it "equals" do
24
- expect(hook).to eql(other)
25
- end
26
- end
27
-
28
- context "with an object having different name" do
29
- let(:other_name) { :red }
30
- let(:other) { object.new(other_name, event_name, other_name) }
31
-
32
- it "doesn't equal" do
33
- expect(hook).not_to eql(other)
34
- end
35
- end
36
- end
@@ -1,13 +0,0 @@
1
- # encoding: utf-8
2
-
3
- RSpec.describe FiniteMachine::HookEvent, '#infer_default_name' do
4
- it "infers default name for state" do
5
- hook_event = described_class::Enter
6
- expect(described_class.infer_default_name(hook_event)).to eq(:any)
7
- end
8
-
9
- it "infers default name for event" do
10
- hook_event = described_class::Before
11
- expect(described_class.infer_default_name(hook_event)).to eq(:any_event)
12
- end
13
- end
@@ -1,25 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe FiniteMachine::HookEvent, '#new' do
6
- it "reads event name" do
7
- hook_event = described_class.new(:green, :go, :green)
8
- expect(hook_event.name).to eql(:green)
9
- end
10
-
11
- it "reads event type" do
12
- hook_event = described_class.new(:green, :go, :green)
13
- expect(hook_event.type).to eql(FiniteMachine::HookEvent)
14
- end
15
-
16
- it "reads the from state" do
17
- hook_event = described_class.new(:green, :go, :red)
18
- expect(hook_event.from).to eql(:red)
19
- end
20
-
21
- it "freezes object" do
22
- hook_event = described_class.new(:green, :go, :green)
23
- expect { hook_event.name = :red }.to raise_error(RuntimeError)
24
- end
25
- end
@@ -1,14 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe FiniteMachine::HookEvent, '.notify' do
6
- it "emits event on the subscriber" do
7
- subscriber = spy(:subscriber)
8
- hook_event = described_class.new(:green, :go, :red)
9
-
10
- hook_event.notify(subscriber, 1, 2)
11
-
12
- expect(subscriber).to have_received(:emit).with(hook_event, 1, 2)
13
- end
14
- end
@@ -1,24 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe FiniteMachine::Hooks, '#call' do
6
- let(:object) { described_class }
7
-
8
- subject(:hooks) { object.new }
9
-
10
- it "adds and removes a single hook" do
11
- expect(hooks).to be_empty
12
-
13
- yielded = []
14
- event_type = FiniteMachine::HookEvent::Before
15
- hook = -> { }
16
- hooks.register(event_type, :foo, hook)
17
-
18
- hooks.call(event_type, :foo) do |callback|
19
- yielded << callback
20
- end
21
-
22
- expect(yielded).to eq([hook])
23
- end
24
- end
@@ -1,16 +0,0 @@
1
- # encoding: utf-8
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,17 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe FiniteMachine::Hooks, '#inspect' do
6
- subject(:hooks) { described_class.new }
7
-
8
- it "displays name and transitions" do
9
- hook = -> { }
10
- event = FiniteMachine::HookEvent::Enter
11
- collection = {event => {yellow: [hook]}}
12
- hooks.register(event, :yellow, hook)
13
-
14
- expect(hooks.inspect).to eql("<#FiniteMachine::Hooks:0x#{hooks.object_id.to_s(16)} @collection=#{collection}>")
15
- expect(hooks.to_s).to eql(hooks.inspect)
16
- end
17
- end
@@ -1,22 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe FiniteMachine::Hooks, '#register' do
6
- let(:object) { described_class }
7
-
8
- subject(:hooks) { object.new }
9
-
10
- it "adds and removes a single hook" do
11
- expect(hooks).to be_empty
12
-
13
- event_type = FiniteMachine::HookEvent::Before
14
- hook = -> { }
15
-
16
- hooks.register(event_type, :foo, hook)
17
- expect(hooks.collection).to eq({event_type => {foo: [hook]}})
18
-
19
- hooks.unregister(event_type, :foo, hook)
20
- expect(hooks.collection).to eq({event_type => {foo: []}})
21
- end
22
- end
@@ -1,353 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe FiniteMachine, ':if, :unless' do
6
- before(:each) {
7
- stub_const("Car", Class.new do
8
- attr_accessor :engine_on
9
-
10
- def turn_engine_on
11
- @engine_on = true
12
- end
13
-
14
- def turn_engine_off
15
- @engine_on = false
16
- end
17
-
18
- def engine_on?
19
- !!@engine_on
20
- end
21
- end)
22
-
23
- stub_const("Bug", Class.new do
24
- def pending?
25
- false
26
- end
27
- end)
28
- }
29
-
30
- it "passes context to conditionals" do
31
- called = []
32
- fsm = FiniteMachine.define do
33
- initial :red
34
-
35
- events {
36
- event :go, :red => :green,
37
- if: proc { |context| called << "cond_red_green(#{context})"; true}
38
- event :stop, from: :any do
39
- choice :red,
40
- if: proc { |context| called << "cond_any_red(#{context})"; true }
41
- end
42
- }
43
- end
44
-
45
- expect(fsm.current).to eq(:red)
46
-
47
- fsm.go
48
- expect(fsm.current).to eq(:green)
49
- expect(called).to eq(["cond_red_green(#{fsm})"])
50
-
51
- fsm.stop
52
- expect(fsm.current).to eq(:red)
53
- expect(called).to match_array([
54
- "cond_red_green(#{fsm})",
55
- "cond_any_red(#{fsm})"
56
- ])
57
- end
58
-
59
- it "passes context & arguments to conditionals" do
60
- called = []
61
- fsm = FiniteMachine.define do
62
- initial :red
63
-
64
- events {
65
- event :go, :red => :green,
66
- if: proc { |_, a| called << "cond_red_green(#{a})"; true }
67
- event :stop, from: :any do
68
- choice :red,
69
- if: proc { |_, b| called << "cond_any_red(#{b})"; true }
70
- end
71
- }
72
- end
73
-
74
- expect(fsm.current).to eq(:red)
75
-
76
- fsm.go(:foo)
77
- expect(fsm.current).to eq(:green)
78
- expect(called).to eq(["cond_red_green(foo)"])
79
-
80
- fsm.stop(:bar)
81
- expect(fsm.current).to eq(:red)
82
- expect(called).to match_array([
83
- "cond_red_green(foo)",
84
- "cond_any_red(bar)"
85
- ])
86
- end
87
-
88
- it "allows to cancel event with :if option" do
89
- called = []
90
-
91
- fsm = FiniteMachine.define do
92
- initial :green
93
-
94
- events {
95
- event :slow, :green => :yellow, if: -> { return false }
96
- event :stop, :yellow => :red
97
- }
98
-
99
- callbacks {
100
- # generic callbacks
101
- on_enter do |event| called << 'on_enter' end
102
- on_transition do |event| called << 'on_transition' end
103
- on_exit do |event| called << 'on_exit' end
104
-
105
- # state callbacks
106
- on_enter :green do |event| called << 'on_enter_green' end
107
- on_enter :yellow do |event| called << "on_enter_yellow" end
108
-
109
- on_transition :green do |event| called << 'on_transition_green' end
110
- on_transition :yellow do |event| called << "on_transition_yellow" end
111
-
112
- on_exit :green do |event| called << 'on_exit_green' end
113
- on_exit :yellow do |event| called << "on_exit_yellow" end
114
- }
115
- end
116
-
117
- expect(fsm.current).to eql(:green)
118
- called = []
119
- fsm.slow
120
- expect(fsm.current).to eql(:green)
121
- expect(called).to eql([])
122
- end
123
-
124
- it "allows to cancel event with :unless option" do
125
- called = []
126
-
127
- fsm = FiniteMachine.define do
128
- initial :green
129
-
130
- events {
131
- event :slow, :green => :yellow, unless: -> { true }
132
- event :stop, :yellow => :red
133
- }
134
-
135
- callbacks {
136
- # generic callbacks
137
- on_enter do |event| called << 'on_enter' end
138
- on_transition do |event| called << 'on_transition' end
139
- on_exit do |event| called << 'on_exit' end
140
-
141
- # state callbacks
142
- on_enter :green do |event| called << 'on_enter_green' end
143
- on_enter :yellow do |event| called << "on_enter_yellow" end
144
-
145
- on_transition :green do |event| called << 'on_transition_green' end
146
- on_transition :yellow do |event| called << "on_transition_yellow" end
147
-
148
- on_exit :green do |event| called << 'on_exit_green' end
149
- on_exit :yellow do |event| called << "on_exit_yellow" end
150
- }
151
- end
152
-
153
- expect(fsm.current).to eql(:green)
154
- called = []
155
- fsm.slow
156
- expect(fsm.current).to eql(:green)
157
- expect(called).to eql([])
158
- end
159
-
160
- it "allows to combine conditionals" do
161
- conditions = []
162
-
163
- fsm = FiniteMachine.define do
164
- initial :green
165
-
166
- events {
167
- event :slow, :green => :yellow,
168
- if: [ -> { conditions << 'first_if'; return true },
169
- -> { conditions << 'second_if'; return true}],
170
- unless: -> { conditions << 'first_unless'; return true }
171
- event :stop, :yellow => :red
172
- }
173
- end
174
-
175
- expect(fsm.current).to eql(:green)
176
- fsm.slow
177
- expect(fsm.current).to eql(:green)
178
- expect(conditions).to eql([
179
- 'first_if',
180
- 'second_if',
181
- 'first_unless'
182
- ])
183
- end
184
-
185
- context 'when proc' do
186
- it "specifies :if and :unless" do
187
- car = Car.new
188
-
189
- fsm = FiniteMachine.define do
190
- initial :neutral
191
-
192
- target car
193
-
194
- events {
195
- event :start, :neutral => :one, if: proc {|_car| _car.engine_on? }
196
- event :shift, :one => :two
197
- }
198
- end
199
- car.turn_engine_off
200
- expect(car.engine_on?).to be false
201
- expect(fsm.current).to eql(:neutral)
202
- fsm.start
203
- expect(fsm.current).to eql(:neutral)
204
-
205
- car.turn_engine_on
206
- expect(car.engine_on?).to be true
207
- expect(fsm.current).to eql(:neutral)
208
- fsm.start
209
- expect(fsm.current).to eql(:one)
210
- end
211
-
212
- it "passes arguments to the scope" do
213
- car = Car.new
214
-
215
- fsm = FiniteMachine.define do
216
- initial :neutral
217
-
218
- target car
219
-
220
- events {
221
- event :start, :neutral => :one, if: proc { |_car, state|
222
- _car.engine_on = state
223
- _car.engine_on?
224
- }
225
- event :shift, :one => :two
226
- }
227
- end
228
- fsm.start(false)
229
- expect(fsm.current).to eql(:neutral)
230
- fsm.start(true)
231
- expect(fsm.current).to eql(:one)
232
- end
233
- end
234
-
235
- context 'when symbol' do
236
- it "specifies :if and :unless" do
237
- car = Car.new
238
-
239
- fsm = FiniteMachine.define do
240
- initial :neutral
241
-
242
- target car
243
-
244
- events {
245
- event :start, :neutral => :one, if: :engine_on?
246
- event :shift, :one => :two
247
- }
248
- end
249
- car.turn_engine_off
250
- expect(car.engine_on?).to be false
251
- expect(fsm.current).to eql(:neutral)
252
- fsm.start
253
- expect(fsm.current).to eql(:neutral)
254
-
255
- car.turn_engine_on
256
- expect(car.engine_on?).to be true
257
- expect(fsm.current).to eql(:neutral)
258
- fsm.start
259
- expect(fsm.current).to eql(:one)
260
- end
261
- end
262
-
263
- context 'when string' do
264
- it "specifies :if and :unless" do
265
- car = Car.new
266
-
267
- fsm = FiniteMachine.define do
268
- initial :neutral
269
-
270
- target car
271
-
272
- events {
273
- event :start, :neutral => :one, if: "engine_on?"
274
- event :shift, :one => :two
275
- }
276
- end
277
- car.turn_engine_off
278
- expect(car.engine_on?).to be false
279
- expect(fsm.current).to eql(:neutral)
280
- fsm.start
281
- expect(fsm.current).to eql(:neutral)
282
-
283
- car.turn_engine_on
284
- expect(car.engine_on?).to be true
285
- expect(fsm.current).to eql(:neutral)
286
- fsm.start
287
- expect(fsm.current).to eql(:one)
288
- end
289
- end
290
-
291
- context 'when same event name' do
292
- it "preservers conditions for the same named event" do
293
- bug = Bug.new
294
- fsm = FiniteMachine.define do
295
- initial :initial
296
-
297
- target bug
298
-
299
- events {
300
- event :bump, :initial => :low
301
- event :bump, :low => :medium, if: :pending?
302
- event :bump, :medium => :high
303
- }
304
- end
305
- expect(fsm.current).to eq(:initial)
306
- fsm.bump
307
- expect(fsm.current).to eq(:low)
308
- fsm.bump
309
- expect(fsm.current).to eq(:low)
310
- end
311
-
312
- it "allows for static choice based on branching condition" do
313
- fsm = FiniteMachine.define do
314
- initial :company_form
315
-
316
- events {
317
- event :next, :company_form => :agreement_form, if: -> { false }
318
- event :next, :company_form => :promo_form, if: -> { false }
319
- event :next, :company_form => :official_form, if: -> { true }
320
- }
321
- end
322
- expect(fsm.current).to eq(:company_form)
323
- fsm.next
324
- expect(fsm.current).to eq(:official_form)
325
- end
326
-
327
- it "allows for dynamic choice based on branching condition" do
328
- fsm = FiniteMachine.define do
329
- initial :company_form
330
-
331
- events {
332
- event :next, :company_form => :agreement_form, if: proc { |_, a| a < 1 }
333
- event :next, :company_form => :promo_form, if: proc { |_, a| a == 1 }
334
- event :next, :company_form => :official_form, if: proc { |_, a| a > 1 }
335
- }
336
- end
337
- expect(fsm.current).to eq(:company_form)
338
-
339
- fsm.next(0)
340
- expect(fsm.current).to eq(:agreement_form)
341
- fsm.restore!(:company_form)
342
- expect(fsm.current).to eq(:company_form)
343
-
344
- fsm.next(1)
345
- expect(fsm.current).to eq(:promo_form)
346
- fsm.restore!(:company_form)
347
- expect(fsm.current).to eq(:company_form)
348
-
349
- fsm.next(2)
350
- expect(fsm.current).to eq(:official_form)
351
- end
352
- end
353
- end