finite_machine 0.3.0 → 0.4.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.
@@ -150,6 +150,21 @@ describe FiniteMachine, 'events' do
150
150
  expect { fsm.stop }.to raise_error(FiniteMachine::InvalidStateError, /state 'green'/)
151
151
  end
152
152
 
153
+ it "allows to transition to any state" do
154
+ fsm = FiniteMachine.define do
155
+ initial :green
156
+
157
+ events {
158
+ event :slow, from: :green, to: :yellow
159
+ event :stop, from: :yellow, to: :red
160
+ }
161
+ end
162
+ expect(fsm.current).to eql(:green)
163
+ expect(fsm.can?(:stop)).to be_false
164
+ fsm.stop!
165
+ expect(fsm.current).to eql(:red)
166
+ end
167
+
153
168
  context 'when multiple from states' do
154
169
  it "allows for array from key" do
155
170
  fsm = FiniteMachine.define do
@@ -5,6 +5,8 @@ require 'spec_helper'
5
5
  describe FiniteMachine, ':if, :unless' do
6
6
  before(:each) {
7
7
  Car = Class.new do
8
+ attr_accessor :engine_on
9
+
8
10
  def turn_engine_on
9
11
  @engine_on = true
10
12
  end
@@ -116,81 +118,109 @@ describe FiniteMachine, ':if, :unless' do
116
118
  ])
117
119
  end
118
120
 
119
- it "specifies :if and :unless with proc" do
120
- car = Car.new
121
+ context 'when proc' do
122
+ it "specifies :if and :unless" do
123
+ car = Car.new
121
124
 
122
- fsm = FiniteMachine.define do
123
- initial :neutral
125
+ fsm = FiniteMachine.define do
126
+ initial :neutral
124
127
 
125
- target car
128
+ target car
126
129
 
127
- events {
128
- event :start, :neutral => :one, if: proc {|_car| _car.engine_on? }
129
- event :shift, :one => :two
130
- }
130
+ events {
131
+ event :start, :neutral => :one, if: proc {|_car| _car.engine_on? }
132
+ event :shift, :one => :two
133
+ }
134
+ end
135
+ car.turn_engine_off
136
+ expect(car.engine_on?).to be_false
137
+ expect(fsm.current).to eql(:neutral)
138
+ fsm.start
139
+ expect(fsm.current).to eql(:neutral)
140
+
141
+ car.turn_engine_on
142
+ expect(car.engine_on?).to be_true
143
+ expect(fsm.current).to eql(:neutral)
144
+ fsm.start
145
+ expect(fsm.current).to eql(:one)
146
+ end
147
+
148
+ it "passes arguments to the scope" do
149
+ car = Car.new
150
+
151
+ fsm = FiniteMachine.define do
152
+ initial :neutral
153
+
154
+ target car
155
+
156
+ events {
157
+ event :start, :neutral => :one, if: proc { |_car, state|
158
+ _car.engine_on = state
159
+ _car.engine_on?
160
+ }
161
+ event :shift, :one => :two
162
+ }
163
+ end
164
+ fsm.start(false)
165
+ expect(fsm.current).to eql(:neutral)
166
+ fsm.start(true)
167
+ expect(fsm.current).to eql(:one)
131
168
  end
132
- car.turn_engine_off
133
- expect(car.engine_on?).to be_false
134
- expect(fsm.current).to eql(:neutral)
135
- fsm.start
136
- expect(fsm.current).to eql(:neutral)
137
-
138
- car.turn_engine_on
139
- expect(car.engine_on?).to be_true
140
- expect(fsm.current).to eql(:neutral)
141
- fsm.start
142
- expect(fsm.current).to eql(:one)
143
169
  end
144
170
 
145
- it "specifies :if and :unless with symbol" do
146
- car = Car.new
171
+ context 'when symbol' do
172
+ it "specifies :if and :unless" do
173
+ car = Car.new
147
174
 
148
- fsm = FiniteMachine.define do
149
- initial :neutral
175
+ fsm = FiniteMachine.define do
176
+ initial :neutral
150
177
 
151
- target car
178
+ target car
152
179
 
153
- events {
154
- event :start, :neutral => :one, if: :engine_on?
155
- event :shift, :one => :two
156
- }
180
+ events {
181
+ event :start, :neutral => :one, if: :engine_on?
182
+ event :shift, :one => :two
183
+ }
184
+ end
185
+ car.turn_engine_off
186
+ expect(car.engine_on?).to be_false
187
+ expect(fsm.current).to eql(:neutral)
188
+ fsm.start
189
+ expect(fsm.current).to eql(:neutral)
190
+
191
+ car.turn_engine_on
192
+ expect(car.engine_on?).to be_true
193
+ expect(fsm.current).to eql(:neutral)
194
+ fsm.start
195
+ expect(fsm.current).to eql(:one)
157
196
  end
158
- car.turn_engine_off
159
- expect(car.engine_on?).to be_false
160
- expect(fsm.current).to eql(:neutral)
161
- fsm.start
162
- expect(fsm.current).to eql(:neutral)
163
-
164
- car.turn_engine_on
165
- expect(car.engine_on?).to be_true
166
- expect(fsm.current).to eql(:neutral)
167
- fsm.start
168
- expect(fsm.current).to eql(:one)
169
197
  end
170
198
 
171
- it "specifies :if and :unless with string" do
172
- car = Car.new
199
+ context 'when string' do
200
+ it "specifies :if and :unless" do
201
+ car = Car.new
173
202
 
174
- fsm = FiniteMachine.define do
175
- initial :neutral
203
+ fsm = FiniteMachine.define do
204
+ initial :neutral
176
205
 
177
- target car
206
+ target car
178
207
 
179
- events {
180
- event :start, :neutral => :one, if: "engine_on?"
181
- event :shift, :one => :two
182
- }
208
+ events {
209
+ event :start, :neutral => :one, if: "engine_on?"
210
+ event :shift, :one => :two
211
+ }
212
+ end
213
+ car.turn_engine_off
214
+ expect(car.engine_on?).to be_false
215
+ expect(fsm.current).to eql(:neutral)
216
+ fsm.start
217
+ expect(fsm.current).to eql(:neutral)
218
+
219
+ car.turn_engine_on
220
+ expect(car.engine_on?).to be_true
221
+ expect(fsm.current).to eql(:neutral)
222
+ fsm.start
223
+ expect(fsm.current).to eql(:one)
183
224
  end
184
- car.turn_engine_off
185
- expect(car.engine_on?).to be_false
186
- expect(fsm.current).to eql(:neutral)
187
- fsm.start
188
- expect(fsm.current).to eql(:neutral)
189
-
190
- car.turn_engine_on
191
- expect(car.engine_on?).to be_true
192
- expect(fsm.current).to eql(:neutral)
193
- fsm.start
194
- expect(fsm.current).to eql(:one)
195
225
  end
196
226
  end
@@ -25,7 +25,22 @@ describe FiniteMachine, 'initialize' do
25
25
  expect(fsm.current).to eql(:none)
26
26
  end
27
27
 
28
+ it "requires initial state transition from :none" do
29
+ fsm = FiniteMachine.define do
30
+ events {
31
+ event :init, :none => :green
32
+ event :slow, :green => :yellow
33
+ event :stop, :yellow => :red
34
+ }
35
+ end
36
+
37
+ expect(fsm.current).to eql(:none)
38
+ fsm.init
39
+ expect(fsm.current).to eql(:green)
40
+ end
41
+
28
42
  it "allows to specify inital state" do
43
+ called = []
29
44
  fsm = FiniteMachine.define do
30
45
  initial :green
31
46
 
@@ -33,9 +48,12 @@ describe FiniteMachine, 'initialize' do
33
48
  event :slow, :green => :yellow
34
49
  event :stop, :yellow => :red
35
50
  }
51
+ callbacks {
52
+ on_enter :green do |event| called << 'on_enter_green' end
53
+ }
36
54
  end
37
-
38
55
  expect(fsm.current).to eql(:green)
56
+ expect(called).to be_empty
39
57
  end
40
58
 
41
59
  it "allows to specify deferred inital state" do
@@ -48,10 +66,24 @@ describe FiniteMachine, 'initialize' do
48
66
  }
49
67
  end
50
68
 
69
+ expect(fsm.current).to eql(:none)
51
70
  fsm.init
52
71
  expect(fsm.current).to eql(:green)
53
72
  end
54
73
 
74
+ it "raises error when specyfying initial without state name" do
75
+ expect {
76
+ FiniteMachine.define do
77
+ initial defer: true
78
+
79
+ events {
80
+ event :slow, :green => :yellow
81
+ event :stop, :yellow => :red
82
+ }
83
+ end
84
+ }.to raise_error(FiniteMachine::MissingInitialStateError)
85
+ end
86
+
55
87
  it "allows to specify inital start event" do
56
88
  fsm = FiniteMachine.define do
57
89
  initial state: :green, event: :start
@@ -96,4 +128,19 @@ describe FiniteMachine, 'initialize' do
96
128
  end
97
129
  expect(fsm.current).to eql(:pending)
98
130
  end
131
+
132
+ it "doesn't care about state type" do
133
+ fsm = FiniteMachine.define do
134
+ initial 1
135
+ events {
136
+ event :a, 1 => 2
137
+ event :b, 2 => 3
138
+ }
139
+ end
140
+ expect(fsm.current).to eql(1)
141
+ fsm.a
142
+ expect(fsm.current).to eql(2)
143
+ fsm.b
144
+ expect(fsm.current).to eql(3)
145
+ end
99
146
  end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe FiniteMachine::Transition, 'inspect' do
6
+ let(:machine) { double }
7
+
8
+ subject(:transition) { described_class.new(machine, attrs) }
9
+
10
+ context 'when inspecting' do
11
+ let(:attrs) { {name: :start, :foo => :bar } }
12
+
13
+ it "displays name and transitions" do
14
+ expect(transition.inspect).to eql("<FiniteMachine::Transition name: start, transitions: [:foo] => bar, 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")
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'logger'
5
+
6
+ describe FiniteMachine::Logger do
7
+ let(:message) { 'error' }
8
+ let(:log) { double }
9
+
10
+ subject(:logger) { described_class }
11
+
12
+ before { FiniteMachine.stub(:logger) { log } }
13
+
14
+ it "debugs message call" do
15
+ expect(log).to receive(:debug).with(message)
16
+ logger.debug(message)
17
+ end
18
+
19
+ it "informs message call" do
20
+ expect(log).to receive(:info).with(message)
21
+ logger.info(message)
22
+ end
23
+
24
+ it "warns message call" do
25
+ expect(log).to receive(:warn).with(message)
26
+ logger.warn(message)
27
+ end
28
+
29
+ it "errors message call" do
30
+ expect(log).to receive(:error).with(message)
31
+ logger.error(message)
32
+ end
33
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe FiniteMachine::Subscribers do
6
+ let(:machine) { double }
7
+ let(:event) { double }
8
+ let(:listener) { double }
9
+
10
+ subject(:subscribers) { described_class.new(machine) }
11
+
12
+ before { subscribers.subscribe(listener) }
13
+
14
+ it "checks if any subscribers exist" do
15
+ expect(subscribers.empty?).to be_false
16
+ end
17
+
18
+ it "returns index for the subscriber" do
19
+ expect(subscribers.index(listener)).to eql(0)
20
+ end
21
+
22
+ it "visits all subscribed listeners for the event" do
23
+ expect(event).to receive(:notify).with(listener)
24
+ subscribers.visit(event)
25
+ end
26
+
27
+ it "resets the subscribers" do
28
+ subscribers.reset
29
+ expect(subscribers.empty?).to be_true
30
+ end
31
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: finite_machine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Murach
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-30 00:00:00.000000000 Z
11
+ date: 2014-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -43,6 +43,8 @@ files:
43
43
  - LICENSE.txt
44
44
  - README.md
45
45
  - Rakefile
46
+ - examples/atm.rb
47
+ - examples/bug_system.rb
46
48
  - finite_machine.gemspec
47
49
  - lib/finite_machine.rb
48
50
  - lib/finite_machine/async_call.rb
@@ -53,6 +55,7 @@ files:
53
55
  - lib/finite_machine/event.rb
54
56
  - lib/finite_machine/event_queue.rb
55
57
  - lib/finite_machine/hooks.rb
58
+ - lib/finite_machine/logger.rb
56
59
  - lib/finite_machine/observer.rb
57
60
  - lib/finite_machine/state_machine.rb
58
61
  - lib/finite_machine/subscribers.rb
@@ -71,8 +74,11 @@ files:
71
74
  - spec/unit/handlers_spec.rb
72
75
  - spec/unit/if_unless_spec.rb
73
76
  - spec/unit/initialize_spec.rb
77
+ - spec/unit/inspect_spec.rb
74
78
  - spec/unit/is_spec.rb
79
+ - spec/unit/logger_spec.rb
75
80
  - spec/unit/states_spec.rb
81
+ - spec/unit/subscribers_spec.rb
76
82
  - spec/unit/target_spec.rb
77
83
  - spec/unit/transition/parse_states_spec.rb
78
84
  - tasks/console.rake
@@ -114,8 +120,11 @@ test_files:
114
120
  - spec/unit/handlers_spec.rb
115
121
  - spec/unit/if_unless_spec.rb
116
122
  - spec/unit/initialize_spec.rb
123
+ - spec/unit/inspect_spec.rb
117
124
  - spec/unit/is_spec.rb
125
+ - spec/unit/logger_spec.rb
118
126
  - spec/unit/states_spec.rb
127
+ - spec/unit/subscribers_spec.rb
119
128
  - spec/unit/target_spec.rb
120
129
  - spec/unit/transition/parse_states_spec.rb
121
130
  has_rdoc: