finite_machine 0.2.0 → 0.3.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.
@@ -8,12 +8,16 @@ describe FiniteMachine::Callable, '#call' do
8
8
  Car = Class.new do
9
9
  attr_reader :result
10
10
 
11
+ def initialize
12
+ @engine_on = false
13
+ end
14
+
11
15
  def turn_engine_on
12
16
  @result = 'turn_engine_on'
13
17
  @engine_on = true
14
18
  end
15
19
 
16
- def set_engine(value)
20
+ def set_engine(value = :on)
17
21
  @result = "set_engine(#{value})"
18
22
  @engine = value.to_sym == :on
19
23
  end
@@ -54,12 +58,30 @@ describe FiniteMachine::Callable, '#call' do
54
58
  end
55
59
  end
56
60
 
61
+ context 'when string with arguments' do
62
+ let(:object) { 'set_engine' }
63
+
64
+ it 'executes method with arguments' do
65
+ instance.call(target, :off)
66
+ expect(target.result).to eql('set_engine(off)')
67
+ end
68
+ end
69
+
57
70
  context 'when symbol' do
58
- let(:object) { :engine_on? }
71
+ let(:object) { :set_engine }
59
72
 
60
73
  it 'executes method on target' do
61
74
  instance.call(target)
62
- expect(target.result).to eql('engine_on')
75
+ expect(target.result).to eql('set_engine(on)')
76
+ end
77
+ end
78
+
79
+ context 'when symbol with arguments' do
80
+ let(:object) { :set_engine }
81
+
82
+ it 'executes method on target' do
83
+ instance.call(target, :off)
84
+ expect(target.result).to eql('set_engine(off)')
63
85
  end
64
86
  end
65
87
 
@@ -47,6 +47,8 @@ describe FiniteMachine, 'callbacks' do
47
47
  }
48
48
  end
49
49
 
50
+ expect(fsm.current).to eql(:green)
51
+
50
52
  expect(called).to eql([
51
53
  'on_exit_none',
52
54
  'on_exit',
@@ -394,9 +396,9 @@ describe FiniteMachine, 'callbacks' do
394
396
 
395
397
  callbacks {
396
398
  # generic callbacks
397
- on_enter &callback
398
- on_transition &callback
399
- on_exit &callback
399
+ on_enter(&callback)
400
+ on_transition(&callback)
401
+ on_exit(&callback)
400
402
 
401
403
  # state callbacks
402
404
  on_enter :green, &callback
@@ -471,5 +473,109 @@ describe FiniteMachine, 'callbacks' do
471
473
  expect { fsm.slow }.to raise_error(RuntimeError)
472
474
  end
473
475
 
474
- xit "executes callbacks with multiple 'from' transitions"
476
+ it "executes callbacks with multiple 'from' transitions" do
477
+ called = []
478
+ fsm = FiniteMachine.define do
479
+ initial :green
480
+
481
+ events {
482
+ event :stop, :green => :yellow
483
+ event :stop, :yellow => :red
484
+ }
485
+
486
+ callbacks {
487
+ on_enter_stop do |event|
488
+ called << 'on_enter_stop'
489
+ end
490
+ }
491
+ end
492
+ expect(fsm.current).to eql(:green)
493
+ fsm.stop
494
+ expect(fsm.current).to eql(:yellow)
495
+ fsm.stop
496
+ expect(fsm.current).to eql(:red)
497
+ expect(called).to eql([
498
+ 'on_enter_stop',
499
+ 'on_enter_stop'
500
+ ])
501
+ end
502
+
503
+ it "allows to define callbacks on machine instance" do
504
+ called = []
505
+ fsm = FiniteMachine.define do
506
+ initial :green
507
+
508
+ events {
509
+ event :slow, :green => :yellow
510
+ event :stop, :yellow => :red
511
+ event :ready, :red => :yellow
512
+ event :go, :yellow => :green
513
+ }
514
+ end
515
+
516
+ fsm.on_enter_yellow do |event|
517
+ called << 'on_enter_yellow'
518
+ end
519
+
520
+ expect(fsm.current).to eql(:green)
521
+ fsm.slow
522
+ expect(called).to eql([
523
+ 'on_enter_yellow'
524
+ ])
525
+ end
526
+
527
+ it "raises error for unknown callback" do
528
+ expect { FiniteMachine.define do
529
+ initial :green
530
+
531
+ events {
532
+ event :slow, :green => :yellow
533
+ event :stop, :yellow => :red
534
+ event :ready, :red => :yellow
535
+ event :go, :yellow => :green
536
+ }
537
+
538
+ callbacks {
539
+ on_enter_unknown do |event| end
540
+ }
541
+ end }.to raise_error(NoMethodError)
542
+ end
543
+
544
+ it "triggers callbacks only once" do
545
+ called = []
546
+ fsm = FiniteMachine.define do
547
+ initial :green
548
+
549
+ events {
550
+ event :slow, :green => :yellow
551
+ event :go, :yellow => :green
552
+ }
553
+
554
+ callbacks {
555
+ once_on_enter_green do |event| called << 'once_on_enter_green' end
556
+ once_on_enter_yellow do |event| called << 'once_on_enter_yellow' end
557
+
558
+ once_on_transition_green do |event| called << 'once_on_transition_green' end
559
+ once_on_transition_yellow do |event| called << 'once_on_transition_yellow' end
560
+
561
+ once_on_exit_green do |event| called << 'once_on_exit_green' end
562
+ once_on_exit_yellow do |event| called << 'once_on_exit_yellow' end
563
+ }
564
+ end
565
+ expect(fsm.current).to eql(:green)
566
+ fsm.slow
567
+ expect(fsm.current).to eql(:yellow)
568
+ fsm.go
569
+ expect(fsm.current).to eql(:green)
570
+ fsm.slow
571
+ expect(fsm.current).to eql(:yellow)
572
+ expect(called).to eql([
573
+ 'once_on_transition_green',
574
+ 'once_on_enter_green',
575
+ 'once_on_exit_green',
576
+ 'once_on_transition_yellow',
577
+ 'once_on_enter_yellow',
578
+ 'once_on_exit_yellow'
579
+ ])
580
+ end
475
581
  end
@@ -216,6 +216,7 @@ describe FiniteMachine, 'events' do
216
216
  event :stop, :green => :yellow
217
217
  event :stop, :yellow => :red
218
218
  event :stop, :red => :pink
219
+ event :cycle, [:yellow, :red, :pink] => :green
219
220
  }
220
221
  end
221
222
 
@@ -229,6 +230,10 @@ describe FiniteMachine, 'events' do
229
230
  expect(fsm.current).to eql(:red)
230
231
  fsm.stop
231
232
  expect(fsm.current).to eql(:pink)
233
+ fsm.cycle
234
+ expect(fsm.current).to eql(:green)
235
+ fsm.stop
236
+ expect(fsm.current).to eql(:yellow)
232
237
  end
233
238
 
234
239
  it "returns values for events" do
@@ -96,4 +96,57 @@ describe FiniteMachine, 'handlers' do
96
96
  expect(fsm.current).to eql(:green)
97
97
  expect(called).to eql(['invalid_state_error'])
98
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
99
152
  end
@@ -125,7 +125,7 @@ describe FiniteMachine, ':if, :unless' do
125
125
  target car
126
126
 
127
127
  events {
128
- event :start, :neutral => :one, if: proc {|car| car.engine_on? }
128
+ event :start, :neutral => :one, if: proc {|_car| _car.engine_on? }
129
129
  event :shift, :one => :two
130
130
  }
131
131
  end
data/spec/unit/is_spec.rb CHANGED
@@ -30,4 +30,26 @@ describe FiniteMachine, 'is?' do
30
30
  expect(fsm.is?([:green, :red])).to be_false
31
31
  expect(fsm.is?([:yellow, :red])).to be_true
32
32
  end
33
+
34
+ it "defines helper methods to check current state" do
35
+ fsm = FiniteMachine.define do
36
+ initial :green
37
+
38
+ events {
39
+ event :slow, :green => :yellow
40
+ event :stop, :yellow => :red
41
+ event :ready, :red => :yellow
42
+ event :go, :yellow => :green
43
+ }
44
+ end
45
+ expect(fsm.current).to eql(:green)
46
+
47
+ expect(fsm.green?).to be_true
48
+ expect(fsm.yellow?).to be_false
49
+
50
+ fsm.slow
51
+
52
+ expect(fsm.green?).to be_false
53
+ expect(fsm.yellow?).to be_true
54
+ end
33
55
  end
@@ -53,6 +53,23 @@ describe FiniteMachine, '#target' do
53
53
  expect(car.reverse_lights).to be_false
54
54
  end
55
55
 
56
+ it "propagates method call" do
57
+ fsm = FiniteMachine.define do
58
+ initial :green
59
+ events {
60
+ event :slow, :green => :yellow
61
+ }
62
+
63
+ callbacks {
64
+ on_enter_yellow do |event|
65
+ uknown_method
66
+ end
67
+ }
68
+ end
69
+ expect(fsm.current).to eql(:green)
70
+ expect { fsm.slow }.to raise_error(StandardError)
71
+ end
72
+
56
73
  it "references machine methods inside callback" do
57
74
  called = []
58
75
  fsm = FiniteMachine.define do
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ desc 'Load gem inside irb console'
4
+ task :console do
5
+ require 'irb'
6
+ require 'irb/completion'
7
+ require File.join(__FILE__, '../lib/finite_machine')
8
+ ARGV.clear
9
+ IRB.start
10
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ desc 'Measure code coverage'
4
+ task :coverage do
5
+ begin
6
+ original, ENV['COVERAGE'] = ENV['COVERAGE'], 'true'
7
+ Rake::Task['spec'].invoke
8
+ ensure
9
+ ENV['COVERAGE'] = original
10
+ end
11
+ end
data/tasks/spec.rake ADDED
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc 'Run all specs'
7
+ RSpec::Core::RakeTask.new(:spec) do |task|
8
+ task.pattern = 'spec/{unit,integration}{,/*/**}/*_spec.rb'
9
+ end
10
+
11
+ namespace :spec do
12
+ desc 'Run unit specs'
13
+ RSpec::Core::RakeTask.new(:unit) do |task|
14
+ task.pattern = 'spec/unit{,/*/**}/*_spec.rb'
15
+ end
16
+
17
+ desc 'Run integration specs'
18
+ RSpec::Core::RakeTask.new(:integration) do |task|
19
+ task.pattern = 'spec/integration{,/*/**}/*_spec.rb'
20
+ end
21
+ end
22
+
23
+ rescue LoadError
24
+ %w[spec spec:unit spec:integration].each do |name|
25
+ task name do
26
+ $stderr.puts "In order to run #{name}, do `gem install rspec`"
27
+ end
28
+ end
29
+ 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.2.0
4
+ version: 0.3.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-01 00:00:00.000000000 Z
11
+ date: 2014-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,42 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: '1.3'
19
+ version: '1.5'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: '1.3'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - '>='
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: rspec
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - '>='
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - '>='
53
- - !ruby/object:Gem::Version
54
- version: '0'
26
+ version: '1.5'
55
27
  description: A minimal finite state machine with a straightforward syntax. You can
56
28
  quickly model states, add callbacks and use object-oriented techniques to integrate
57
29
  with ORMs.
@@ -63,6 +35,8 @@ extra_rdoc_files: []
63
35
  files:
64
36
  - .gitignore
65
37
  - .rspec
38
+ - .ruby-gemset
39
+ - .ruby-version
66
40
  - .travis.yml
67
41
  - CHANGELOG.md
68
42
  - Gemfile
@@ -71,18 +45,23 @@ files:
71
45
  - Rakefile
72
46
  - finite_machine.gemspec
73
47
  - lib/finite_machine.rb
48
+ - lib/finite_machine/async_call.rb
49
+ - lib/finite_machine/async_proxy.rb
74
50
  - lib/finite_machine/callable.rb
75
51
  - lib/finite_machine/catchable.rb
76
52
  - lib/finite_machine/dsl.rb
77
53
  - lib/finite_machine/event.rb
54
+ - lib/finite_machine/event_queue.rb
78
55
  - lib/finite_machine/hooks.rb
79
56
  - lib/finite_machine/observer.rb
80
57
  - lib/finite_machine/state_machine.rb
81
58
  - lib/finite_machine/subscribers.rb
59
+ - lib/finite_machine/thread_context.rb
82
60
  - lib/finite_machine/threadable.rb
83
61
  - lib/finite_machine/transition.rb
84
62
  - lib/finite_machine/version.rb
85
63
  - spec/spec_helper.rb
64
+ - spec/unit/async_events_spec.rb
86
65
  - spec/unit/callable/call_spec.rb
87
66
  - spec/unit/callbacks_spec.rb
88
67
  - spec/unit/can_spec.rb
@@ -96,6 +75,9 @@ files:
96
75
  - spec/unit/states_spec.rb
97
76
  - spec/unit/target_spec.rb
98
77
  - spec/unit/transition/parse_states_spec.rb
78
+ - tasks/console.rake
79
+ - tasks/coverage.rake
80
+ - tasks/spec.rake
99
81
  homepage: https://github.com/peter-murach/finite_machine
100
82
  licenses:
101
83
  - MIT
@@ -122,6 +104,7 @@ specification_version: 4
122
104
  summary: A minimal finite state machine with a straightforward syntax.
123
105
  test_files:
124
106
  - spec/spec_helper.rb
107
+ - spec/unit/async_events_spec.rb
125
108
  - spec/unit/callable/call_spec.rb
126
109
  - spec/unit/callbacks_spec.rb
127
110
  - spec/unit/can_spec.rb
@@ -135,3 +118,4 @@ test_files:
135
118
  - spec/unit/states_spec.rb
136
119
  - spec/unit/target_spec.rb
137
120
  - spec/unit/transition/parse_states_spec.rb
121
+ has_rdoc: