finite_machine 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -46,7 +46,9 @@ describe FiniteMachine, 'define' do
46
46
 
47
47
  expect(fsm.current).to eql(:green)
48
48
  fsm.slow
49
+ expect(fsm.current).to eql(:yellow)
49
50
  fsm.ready
51
+ expect(fsm.current).to eql(:yellow)
50
52
  expect(called).to match_array(['on_enter_yellow', 'error_handler'])
51
53
  end
52
54
  end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe FiniteMachine::Event, '#<<' do
6
+ let(:machine) { double(:machine) }
7
+
8
+ let(:object) { described_class }
9
+
10
+ subject(:event) { object.new(machine, name: :test) }
11
+
12
+ it "adds multiple transitions" do
13
+ transition = double(:transition)
14
+ event << transition
15
+ event << transition
16
+ expect(event.state_transitions).to match_array([transition, transition])
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe FiniteMachine::Event, '#inspect' do
6
+ let(:machine) { double(:machine) }
7
+
8
+ let(:object) { described_class }
9
+
10
+ subject(:event) { object.new(machine, name: :test) }
11
+
12
+ it "adds multiple transitions" do
13
+ transition = double(:transition)
14
+ event << transition
15
+ expect(event.inspect).to eq("<#FiniteMachine::Event @name=test, @transitions=[#{transition.inspect}]>")
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe FiniteMachine::Event, '#next_transition' do
6
+ let(:object) { described_class }
7
+
8
+ subject(:event) { object.new(machine, name: :test) }
9
+
10
+ describe "matches transition by name" do
11
+ let(:machine) { double(:machine, current: :b) }
12
+
13
+ it "finds matching transition" do
14
+ transition_a = double(:transition_a, from_state: :a)
15
+ transition_b = double(:transition_b, from_state: :b)
16
+ event << transition_a
17
+ event << transition_b
18
+
19
+ expect(event.next_transition).to eq(transition_b)
20
+ end
21
+ end
22
+
23
+ describe "matches :any transition" do
24
+ let(:machine) { double(:machine, current: :any) }
25
+
26
+ it "finds matching transition" do
27
+ transition_a = double(:transition_a, from_state: :a)
28
+ transition_any = double(:transition_any, from_state: :any)
29
+ event << transition_a
30
+ event << transition_any
31
+
32
+ expect(event.next_transition).to eq(transition_any)
33
+ end
34
+ end
35
+
36
+ describe "fails to find" do
37
+ let(:machine) { double(:machine, current: :c) }
38
+
39
+ it "choses first available transition" do
40
+ transition_a = double(:transition_a, from_state: :a)
41
+ transition_b = double(:transition_b, from_state: :b)
42
+ event << transition_a
43
+ event << transition_b
44
+
45
+ expect(event.next_transition).to eq(transition_a)
46
+ end
47
+ end
48
+ end
@@ -291,8 +291,8 @@ describe FiniteMachine, 'events' do
291
291
  }
292
292
 
293
293
  callbacks {
294
- on_enter(:drive) { }
295
- on_exit(:stop) { }
294
+ on_before(:drive) { }
295
+ on_after(:stop) { }
296
296
  }
297
297
  end
298
298
 
@@ -302,4 +302,43 @@ describe FiniteMachine, 'events' do
302
302
  expect(fsm.stop).to eql(FiniteMachine::SUCCEEDED)
303
303
  expect(fsm.stop).to eql(FiniteMachine::NOTRANSITION)
304
304
  end
305
+
306
+ it "allows for self transition events" do
307
+ digits = []
308
+ callbacks = []
309
+ phone = FiniteMachine.define do
310
+ initial :on_hook
311
+
312
+ events {
313
+ event :digit, :on_hook => :dialing
314
+ event :digit, :dialing => :dialing
315
+ event :off_hook, :dialing => :alerting
316
+ }
317
+
318
+ callbacks {
319
+ on_before_digit { |event, digit| digits << digit}
320
+ on_before_off_hook { |event| callbacks << "dialing #{digits.join}" }
321
+ }
322
+ end
323
+
324
+ expect(phone.current).to eq(:on_hook)
325
+ phone.digit(9)
326
+ expect(phone.current).to eq(:dialing)
327
+ phone.digit(1)
328
+ expect(phone.current).to eq(:dialing)
329
+ phone.digit(1)
330
+ expect(phone.current).to eq(:dialing)
331
+ phone.off_hook
332
+ expect(phone.current).to eq(:alerting)
333
+ expect(digits).to match_array(digits)
334
+ expect(callbacks).to match_array(["dialing 911"])
335
+ end
336
+
337
+ it "detects dangerous event names" do
338
+ expect { FiniteMachine.define do
339
+ events {
340
+ event :transition, :a => :b
341
+ }
342
+ end }.to raise_error(FiniteMachine::AlreadyDefinedError)
343
+ end
305
344
  end
@@ -0,0 +1,24 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ 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
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ 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
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ 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
@@ -223,4 +223,32 @@ describe FiniteMachine, ':if, :unless' do
223
223
  expect(fsm.current).to eql(:one)
224
224
  end
225
225
  end
226
+
227
+ context 'when same event name' do
228
+ class Bug
229
+ def pending?
230
+ false
231
+ end
232
+ end
233
+
234
+ it "preservers conditions for the same named event" do
235
+ bug = Bug.new
236
+ fsm = FiniteMachine.define do
237
+ initial :initial
238
+
239
+ target bug
240
+
241
+ events {
242
+ event :bump, :initial => :low
243
+ event :bump, :low => :medium, if: :pending?
244
+ event :bump, :medium => :high
245
+ }
246
+ end
247
+ expect(fsm.current).to eq(:initial)
248
+ fsm.bump
249
+ expect(fsm.current).to eq(:low)
250
+ fsm.bump
251
+ expect(fsm.current).to eq(:low)
252
+ end
253
+ end
226
254
  end
@@ -2,24 +2,17 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe FiniteMachine::Transition, 'inspect' do
6
- let(:machine) { double }
5
+ describe FiniteMachine, '#inspect' do
7
6
 
8
- subject(:transition) { described_class.new(machine, attrs) }
7
+ it "print useful information about state machine" do
8
+ fsm = FiniteMachine.define do
9
+ initial :green
9
10
 
10
- context 'when inspecting' do
11
- let(:attrs) { {name: :start, :foo => :bar, :baz => :daz} }
12
-
13
- it "displays name and transitions" do
14
- expect(transition.inspect).to eql("<#FiniteMachine::Transition @name=start, @transitions=foo -> bar, baz -> daz, @when=[]>")
15
- end
16
- end
17
-
18
- context 'when converting to string' do
19
- let(:attrs) { {name: :start, :foo => :bar } }
20
-
21
- it "displays name and transitions" do
22
- expect(transition.to_s).to eql("start")
11
+ events {
12
+ event :slow, :green => :yellow
13
+ event :stop, :yellow => :red
14
+ }
23
15
  end
16
+ expect(fsm.inspect).to match(/^<#FiniteMachine::StateMachine:0x#{fsm.object_id.to_s(16)} @states=\[:none, :green, :yellow, :red\], @events=\[:init, :slow, :stop\], @transitions=.*$/)
24
17
  end
25
18
  end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe FiniteMachine, '#respond_to' do
6
+
7
+ subject(:fsm) {
8
+ Car = Class.new do
9
+ def engine_on?
10
+ true
11
+ end
12
+ end
13
+ FiniteMachine.new target: Car.new do
14
+ initial :green
15
+
16
+ events {
17
+ event :slow, :green => :yellow
18
+ }
19
+ end
20
+ }
21
+
22
+ it "knows about event name" do
23
+ expect(fsm).to respond_to(:slow)
24
+ end
25
+
26
+ it "doesn't know about not implemented call" do
27
+ expect(fsm).not_to respond_to(:not_implemented)
28
+ end
29
+
30
+ it "knows about event callback" do
31
+ expect(fsm).to respond_to(:on_enter_slow)
32
+ end
33
+
34
+ it "knows about target class methods" do
35
+ expect(fsm).to respond_to(:engine_on?)
36
+ end
37
+ end
@@ -133,7 +133,7 @@ describe FiniteMachine, '#target' do
133
133
  turn_reverse_lights_on
134
134
  forward('Piotr!')
135
135
  end
136
- on_enter :forward do |event, name|
136
+ on_before :forward do |event, name|
137
137
  called << "on_enter_forward with #{name}"
138
138
  end
139
139
  }
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe FiniteMachine::Transition, '#inspect' do
6
+ let(:machine) { double(:machine) }
7
+
8
+ subject(:transition) { described_class.new(machine, attrs) }
9
+
10
+ context 'when inspecting' do
11
+ let(:attrs) { {name: :start, parsed_states: { :foo => :bar, :baz => :daz } } }
12
+
13
+ it "displays name and transitions" do
14
+ expect(transition.inspect).to eql("<#FiniteMachine::Transition @name=start, @transitions=foo -> bar, baz -> daz, @when=[]>")
15
+ end
16
+ end
17
+
18
+ context 'when converting to string' do
19
+ let(:attrs) { {name: :start, parsed_states: { :foo => :bar } } }
20
+
21
+ it "displays name and transitions" do
22
+ expect(transition.to_s).to eql("start")
23
+ end
24
+ end
25
+ end
@@ -2,22 +2,13 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe FiniteMachine::Transition, 'parse_states' do
6
-
7
- let(:machine) { double }
5
+ describe FiniteMachine::Transition, 'parsed_states' do
6
+ let(:machine) { double(:machine) }
8
7
 
9
8
  subject(:transition) { described_class.new(machine, attrs) }
10
9
 
11
- context 'without transitions' do
12
- let(:attrs) { { } }
13
-
14
- it "raises exception" do
15
- expect { transition }.to raise_error(FiniteMachine::NotEnoughTransitionsError)
16
- end
17
- end
18
-
19
10
  context 'with :to key only' do
20
- let(:attrs) { { to: :red } }
11
+ let(:attrs) { { parsed_states: { any: :red } } }
21
12
 
22
13
  it "groups states" do
23
14
  expect(transition.from_states).to eq([:any])
@@ -26,17 +17,8 @@ describe FiniteMachine::Transition, 'parse_states' do
26
17
  end
27
18
  end
28
19
 
29
- context 'with :from, :to keys' do
30
- let(:attrs) { {from: [:green, :yellow], to: :red} }
31
-
32
- it "groups states" do
33
- expect(transition.from_states).to match_array(attrs[:from])
34
- expect(transition.to_states).to match_array([:red, :red])
35
- end
36
- end
37
-
38
20
  context 'when from array' do
39
- let(:attrs) { {[:green, :yellow] => :red} }
21
+ let(:attrs) { {parsed_states: { :green => :red, :yellow => :red} } }
40
22
 
41
23
  it "groups states" do
42
24
  expect(transition.from_states).to match_array([:green, :yellow])
@@ -46,9 +28,10 @@ describe FiniteMachine::Transition, 'parse_states' do
46
28
 
47
29
  context 'when hash of states' do
48
30
  let(:attrs) {
49
- { :initial => :low,
50
- :low => :medium,
51
- :medium => :high }
31
+ { parsed_states:
32
+ { :initial => :low,
33
+ :low => :medium,
34
+ :medium => :high } }
52
35
  }
53
36
 
54
37
  it "groups states" do
metadata CHANGED
@@ -1,27 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finite_machine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
5
- prerelease:
4
+ version: 0.7.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Piotr Murach
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-05-10 00:00:00.000000000 Z
11
+ date: 2014-05-26 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
- requirement: &2157086980 !ruby/object:Gem::Requirement
17
- none: false
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
21
19
  version: '1.5'
22
20
  type: :development
23
21
  prerelease: false
24
- version_requirements: *2157086980
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
25
27
  description: A minimal finite state machine with a straightforward syntax. You can
26
28
  quickly model states, add callbacks and use object-oriented techniques to integrate
27
29
  with ORMs.
@@ -52,10 +54,12 @@ files:
52
54
  - lib/finite_machine/dsl.rb
53
55
  - lib/finite_machine/event.rb
54
56
  - lib/finite_machine/event_queue.rb
57
+ - lib/finite_machine/hook_event.rb
55
58
  - lib/finite_machine/hooks.rb
56
59
  - lib/finite_machine/listener.rb
57
60
  - lib/finite_machine/logger.rb
58
61
  - lib/finite_machine/observer.rb
62
+ - lib/finite_machine/safety.rb
59
63
  - lib/finite_machine/state_machine.rb
60
64
  - lib/finite_machine/state_parser.rb
61
65
  - lib/finite_machine/subscribers.rb
@@ -70,20 +74,28 @@ files:
70
74
  - spec/unit/callbacks_spec.rb
71
75
  - spec/unit/can_spec.rb
72
76
  - spec/unit/define_spec.rb
77
+ - spec/unit/event/add_spec.rb
78
+ - spec/unit/event/inspect_spec.rb
79
+ - spec/unit/event/next_transition_spec.rb
73
80
  - spec/unit/event_queue_spec.rb
74
81
  - spec/unit/events_spec.rb
75
82
  - spec/unit/finished_spec.rb
76
83
  - spec/unit/handlers_spec.rb
84
+ - spec/unit/hooks/call_spec.rb
85
+ - spec/unit/hooks/inspect_spec.rb
86
+ - spec/unit/hooks/register_spec.rb
77
87
  - spec/unit/if_unless_spec.rb
78
88
  - spec/unit/initialize_spec.rb
79
89
  - spec/unit/inspect_spec.rb
80
90
  - spec/unit/is_spec.rb
81
91
  - spec/unit/logger_spec.rb
92
+ - spec/unit/respond_to_spec.rb
82
93
  - spec/unit/state_parser/inspect_spec.rb
83
94
  - spec/unit/state_parser/parse_states_spec.rb
84
95
  - spec/unit/states_spec.rb
85
96
  - spec/unit/subscribers_spec.rb
86
97
  - spec/unit/target_spec.rb
98
+ - spec/unit/transition/inspect_spec.rb
87
99
  - spec/unit/transition/parse_states_spec.rb
88
100
  - tasks/console.rake
89
101
  - tasks/coverage.rake
@@ -91,33 +103,26 @@ files:
91
103
  homepage: https://github.com/peter-murach/finite_machine
92
104
  licenses:
93
105
  - MIT
106
+ metadata: {}
94
107
  post_install_message:
95
108
  rdoc_options: []
96
109
  require_paths:
97
110
  - lib
98
111
  required_ruby_version: !ruby/object:Gem::Requirement
99
- none: false
100
112
  requirements:
101
- - - ! '>='
113
+ - - '>='
102
114
  - !ruby/object:Gem::Version
103
115
  version: '0'
104
- segments:
105
- - 0
106
- hash: -2682862058566322230
107
116
  required_rubygems_version: !ruby/object:Gem::Requirement
108
- none: false
109
117
  requirements:
110
- - - ! '>='
118
+ - - '>='
111
119
  - !ruby/object:Gem::Version
112
120
  version: '0'
113
- segments:
114
- - 0
115
- hash: -2682862058566322230
116
121
  requirements: []
117
122
  rubyforge_project:
118
- rubygems_version: 1.8.10
123
+ rubygems_version: 2.0.3
119
124
  signing_key:
120
- specification_version: 3
125
+ specification_version: 4
121
126
  summary: A minimal finite state machine with a straightforward syntax.
122
127
  test_files:
123
128
  - spec/spec_helper.rb
@@ -126,19 +131,27 @@ test_files:
126
131
  - spec/unit/callbacks_spec.rb
127
132
  - spec/unit/can_spec.rb
128
133
  - spec/unit/define_spec.rb
134
+ - spec/unit/event/add_spec.rb
135
+ - spec/unit/event/inspect_spec.rb
136
+ - spec/unit/event/next_transition_spec.rb
129
137
  - spec/unit/event_queue_spec.rb
130
138
  - spec/unit/events_spec.rb
131
139
  - spec/unit/finished_spec.rb
132
140
  - spec/unit/handlers_spec.rb
141
+ - spec/unit/hooks/call_spec.rb
142
+ - spec/unit/hooks/inspect_spec.rb
143
+ - spec/unit/hooks/register_spec.rb
133
144
  - spec/unit/if_unless_spec.rb
134
145
  - spec/unit/initialize_spec.rb
135
146
  - spec/unit/inspect_spec.rb
136
147
  - spec/unit/is_spec.rb
137
148
  - spec/unit/logger_spec.rb
149
+ - spec/unit/respond_to_spec.rb
138
150
  - spec/unit/state_parser/inspect_spec.rb
139
151
  - spec/unit/state_parser/parse_states_spec.rb
140
152
  - spec/unit/states_spec.rb
141
153
  - spec/unit/subscribers_spec.rb
142
154
  - spec/unit/target_spec.rb
155
+ - spec/unit/transition/inspect_spec.rb
143
156
  - spec/unit/transition/parse_states_spec.rb
144
157
  has_rdoc: