finite_machine 0.6.1 → 0.7.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.
@@ -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: