state-fu 0.11.1
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.
- data/LICENSE +40 -0
- data/README.textile +293 -0
- data/Rakefile +114 -0
- data/lib/binding.rb +292 -0
- data/lib/event.rb +192 -0
- data/lib/executioner.rb +120 -0
- data/lib/hooks.rb +39 -0
- data/lib/interface.rb +132 -0
- data/lib/lathe.rb +538 -0
- data/lib/machine.rb +184 -0
- data/lib/method_factory.rb +243 -0
- data/lib/persistence.rb +116 -0
- data/lib/persistence/active_record.rb +34 -0
- data/lib/persistence/attribute.rb +47 -0
- data/lib/persistence/base.rb +100 -0
- data/lib/persistence/relaxdb.rb +23 -0
- data/lib/persistence/session.rb +7 -0
- data/lib/sprocket.rb +58 -0
- data/lib/state-fu.rb +56 -0
- data/lib/state.rb +48 -0
- data/lib/support/active_support_lite/array.rb +9 -0
- data/lib/support/active_support_lite/array/access.rb +60 -0
- data/lib/support/active_support_lite/array/conversions.rb +202 -0
- data/lib/support/active_support_lite/array/extract_options.rb +21 -0
- data/lib/support/active_support_lite/array/grouping.rb +109 -0
- data/lib/support/active_support_lite/array/random_access.rb +13 -0
- data/lib/support/active_support_lite/array/wrapper.rb +25 -0
- data/lib/support/active_support_lite/blank.rb +67 -0
- data/lib/support/active_support_lite/cattr_reader.rb +57 -0
- data/lib/support/active_support_lite/keys.rb +57 -0
- data/lib/support/active_support_lite/misc.rb +59 -0
- data/lib/support/active_support_lite/module.rb +1 -0
- data/lib/support/active_support_lite/module/delegation.rb +130 -0
- data/lib/support/active_support_lite/object.rb +9 -0
- data/lib/support/active_support_lite/string.rb +38 -0
- data/lib/support/active_support_lite/symbol.rb +16 -0
- data/lib/support/applicable.rb +41 -0
- data/lib/support/arrays.rb +197 -0
- data/lib/support/core_ext.rb +90 -0
- data/lib/support/exceptions.rb +106 -0
- data/lib/support/has_options.rb +16 -0
- data/lib/support/logger.rb +165 -0
- data/lib/support/methodical.rb +17 -0
- data/lib/support/no_stdout.rb +55 -0
- data/lib/support/plotter.rb +62 -0
- data/lib/support/vizier.rb +300 -0
- data/lib/tasks/spec_last.rake +55 -0
- data/lib/tasks/state_fu.rake +57 -0
- data/lib/transition.rb +338 -0
- data/lib/transition_query.rb +224 -0
- data/spec/custom_formatter.rb +49 -0
- data/spec/features/binding_and_transition_helper_mixin_spec.rb +111 -0
- data/spec/features/method_missing_only_once_spec.rb +28 -0
- data/spec/features/not_requirements_spec.rb +118 -0
- data/spec/features/plotter_spec.rb +97 -0
- data/spec/features/shared_log_spec.rb +7 -0
- data/spec/features/singleton_machine_spec.rb +39 -0
- data/spec/features/state_and_array_options_accessor_spec.rb +47 -0
- data/spec/features/transition_boolean_comparison_spec.rb +101 -0
- data/spec/helper.rb +13 -0
- data/spec/integration/active_record_persistence_spec.rb +202 -0
- data/spec/integration/binding_extension_spec.rb +41 -0
- data/spec/integration/class_accessor_spec.rb +117 -0
- data/spec/integration/event_definition_spec.rb +74 -0
- data/spec/integration/example_01_document_spec.rb +133 -0
- data/spec/integration/example_02_string_spec.rb +88 -0
- data/spec/integration/instance_accessor_spec.rb +97 -0
- data/spec/integration/lathe_extension_spec.rb +67 -0
- data/spec/integration/machine_duplication_spec.rb +101 -0
- data/spec/integration/relaxdb_persistence_spec.rb +97 -0
- data/spec/integration/requirement_reflection_spec.rb +270 -0
- data/spec/integration/state_definition_spec.rb +163 -0
- data/spec/integration/transition_spec.rb +1033 -0
- data/spec/spec.opts +9 -0
- data/spec/spec_helper.rb +132 -0
- data/spec/state_fu_spec.rb +948 -0
- data/spec/units/binding_spec.rb +192 -0
- data/spec/units/event_spec.rb +214 -0
- data/spec/units/exceptions_spec.rb +82 -0
- data/spec/units/lathe_spec.rb +570 -0
- data/spec/units/machine_spec.rb +229 -0
- data/spec/units/method_factory_spec.rb +366 -0
- data/spec/units/sprocket_spec.rb +69 -0
- data/spec/units/state_spec.rb +59 -0
- metadata +171 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../helper")
|
2
|
+
|
3
|
+
describe "extending bindings and transitions with Lathe#helper" do
|
4
|
+
|
5
|
+
include MySpecHelper
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
reset!
|
9
|
+
make_pristine_class('Klass')
|
10
|
+
|
11
|
+
@machine = Klass.state_fu_machine do
|
12
|
+
state :normal, :colour => 'green'
|
13
|
+
state :bad, :colour => 'red'
|
14
|
+
event( :worsen, :colour => 'orange' ) { from :normal => :bad }
|
15
|
+
end
|
16
|
+
@obj = Klass.new
|
17
|
+
@binding = @obj.state_fu
|
18
|
+
|
19
|
+
end # before
|
20
|
+
|
21
|
+
describe "accessing sprocket options" do
|
22
|
+
describe "state#[]" do
|
23
|
+
it "should return state.options[key]" do
|
24
|
+
@machine.states[:normal][:colour].should == 'green'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
describe "event#[]" do
|
28
|
+
it "should return event.options[key]" do
|
29
|
+
@machine.events[:worsen][:colour].should == 'orange'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "state#[]=" do
|
34
|
+
it "should update state.options" do
|
35
|
+
@machine.states[:normal][:flavour] = 'lime'
|
36
|
+
@machine.states[:normal][:flavour].should == 'lime'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
describe "event#[]=" do
|
40
|
+
it "should update event.options" do
|
41
|
+
@machine.events[:worsen][:flavour] = 'orange'
|
42
|
+
@machine.events[:worsen][:flavour].should == 'orange'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
|
2
|
+
|
3
|
+
describe "extending bindings and transitions with Lathe#helper" do
|
4
|
+
|
5
|
+
include MySpecHelper
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
reset!
|
9
|
+
make_pristine_class('Klass')
|
10
|
+
Klass.class_eval do
|
11
|
+
attr_accessor :ok
|
12
|
+
end
|
13
|
+
|
14
|
+
@machine = Klass.machine do
|
15
|
+
chain "a -a2b-> b -b2c-> c"
|
16
|
+
events.each do |e|
|
17
|
+
e.requires :ok
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@obj = Klass.new
|
22
|
+
@binding = @obj.state_fu
|
23
|
+
@transition = @obj.state_fu.transition(:a2b)
|
24
|
+
end # before
|
25
|
+
|
26
|
+
#
|
27
|
+
#
|
28
|
+
|
29
|
+
describe StateFu::Transition do
|
30
|
+
describe "equality" do
|
31
|
+
|
32
|
+
it "should == the current_state" do
|
33
|
+
@transition.should == @transition.current_state
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should != any other state" do
|
37
|
+
@transition.should_not == @transition.target
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should == the current_state_name" do
|
41
|
+
@transition.should == @transition.current_state
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should != any other State's name" do
|
45
|
+
@transition.should_not == @transition.target.name
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "with an unaccepted transition" do
|
49
|
+
before do
|
50
|
+
# stub(@transition).accepted? { false }
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should != true" do
|
54
|
+
@transition.should_not == true
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should == false" do
|
58
|
+
@transition.should == false
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should not === true" do
|
62
|
+
@transition.should_not === true
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should === false" do
|
66
|
+
@transition.should === false
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should not be nil?" do
|
70
|
+
@transition.nil?.should be_false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
describe "with an accepted transition" do
|
76
|
+
before do
|
77
|
+
@obj.ok = true
|
78
|
+
@transition.fire!
|
79
|
+
@transition.should be_accepted
|
80
|
+
end
|
81
|
+
it "should == true" do
|
82
|
+
@transition.should == true
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should not == false" do
|
86
|
+
@transition.should_not == false
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should === true" do
|
90
|
+
@transition.should === true
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should not === false" do
|
94
|
+
@transition.should_not === false
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.join(File.dirname(__FILE__),'spec_helper')
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rr'
|
6
|
+
rescue LoadError => e
|
7
|
+
STDERR.puts "The '#{gem_name}' gem is required to run StateFu's specs. Please install it by running (as root):\ngem install #{gem_name}\n\n"
|
8
|
+
exit 1;
|
9
|
+
end
|
10
|
+
|
11
|
+
Spec::Runner.configure do |config|
|
12
|
+
config.mock_with :rr
|
13
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../helper")
|
2
|
+
|
3
|
+
describe "an ActiveRecord model with StateFu included:" do
|
4
|
+
|
5
|
+
include MySpecHelper
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
reset!
|
9
|
+
prepare_active_record() do
|
10
|
+
def self.up
|
11
|
+
create_table :example_records do |t|
|
12
|
+
t.string :name, :null => false
|
13
|
+
t.string :state_fu_field, :null => false
|
14
|
+
t.string :description
|
15
|
+
t.string :status
|
16
|
+
t.timestamps
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# class ExampleRecord < ActiveRecord::Base
|
22
|
+
make_pristine_class( 'ExampleRecord', ActiveRecord::Base )
|
23
|
+
ExampleRecord.class_eval do
|
24
|
+
validates_presence_of :name
|
25
|
+
end
|
26
|
+
# end class ExampleRecord
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be a subclass of ActiveRecord::Base" do
|
30
|
+
ExampleRecord.superclass.should == ActiveRecord::Base
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "when the ActiveRecord model has no table yet (eg before migrations)" do
|
34
|
+
before do
|
35
|
+
make_pristine_class('TableMissingClass', ActiveRecord::Base )
|
36
|
+
TableMissingClass.class_eval do
|
37
|
+
state_fu_machine() { }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should not raise an error when the persister is instantiated" do
|
42
|
+
lambda { TableMissingClass.columns }.should raise_error
|
43
|
+
lambda { TableMissingClass.state_fu_machine }.should_not raise_error
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
describe "when the default machine is defined with no field_name specified" do
|
48
|
+
before do
|
49
|
+
ExampleRecord.class_eval do
|
50
|
+
state_fu_machine do
|
51
|
+
state :initial do
|
52
|
+
event( :change, :to => :final ) { after :save! }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
@ex = ExampleRecord.new( :name => "exemplar" )
|
57
|
+
end # before
|
58
|
+
|
59
|
+
it "should have an active_record string column 'state_fu_field' " do
|
60
|
+
col = ExampleRecord.columns.detect {|c| c.name == "state_fu_field" }
|
61
|
+
col.type.should == :string
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "calling :save! via an event's after hook" do
|
65
|
+
it "should save the record with the new state persisted via the DB" do
|
66
|
+
@ex.change!
|
67
|
+
@ex.state_fu.name.should == :final
|
68
|
+
@ex.state_fu_field.should == 'final'
|
69
|
+
@ex.reload
|
70
|
+
@ex.state_fu_field.should == 'final'
|
71
|
+
@ex.state_fu.name.should == :final
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "StateFu::Persistence.active_record_column?" do
|
76
|
+
it "should return true for ExampleRecord, :state_fu_field" do
|
77
|
+
StateFu::Persistence.active_record_column?( ExampleRecord, :state_fu_field ).should == true
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should return true for ExampleRecord, :status" do
|
81
|
+
StateFu::Persistence.active_record_column?( ExampleRecord, :status ).should == true
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should return false for ExampleRecord, :not_a_column" do
|
85
|
+
StateFu::Persistence.active_record_column?( ExampleRecord, :not_a_column ).should == false
|
86
|
+
end
|
87
|
+
it "should not clobber activerecord accessors" do
|
88
|
+
@ex.noodle! rescue nil
|
89
|
+
# lambda { @ex.description }.should_not raise_error()
|
90
|
+
@ex.description.should be_nil
|
91
|
+
@ex.description= 'foo'
|
92
|
+
@ex.description.should == 'foo'
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should have an active_record string column 'state_fu_field' " do
|
96
|
+
col = ExampleRecord.columns.detect {|c| c.name == "state_fu_field" }
|
97
|
+
col.type.should == :string
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should have an active_record persister with the default field_name 'state_fu_field' " do
|
102
|
+
@ex.state_fu
|
103
|
+
@ex.state_fu.should be_kind_of( StateFu::Binding )
|
104
|
+
@ex.state_fu.persister.should be_kind_of( StateFu::Persistence::ActiveRecord )
|
105
|
+
@ex.state_fu.persister.field_name.should == :state_fu_field
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# this ensures state_fu initializes the field before create to
|
110
|
+
# satisfy the not null constraint
|
111
|
+
describe "automagic state_fu! before_save filter and validations" do
|
112
|
+
|
113
|
+
it "should call state_fu! before a record is created" do
|
114
|
+
@ex.should be_new_record
|
115
|
+
mock.proxy( @ex ).state_fu!.at_least( 1 ) { }
|
116
|
+
@ex.save!
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should call state_fu! before a record is updated" do
|
120
|
+
@ex.should be_new_record
|
121
|
+
mock.proxy( @ex ).state_fu!.at_least( 1 ) { }
|
122
|
+
@ex.save!
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should fail to save if state_fu! does not instantiate the binding before create" do
|
126
|
+
mock( @ex ).state_fu!.at_least( 1 ) { }
|
127
|
+
lambda { @ex.save! }.should raise_error( ActiveRecord::StatementInvalid )
|
128
|
+
@ex.state_fu_field.should == nil
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should create a record given only a name, with the field set to the initial state" do
|
132
|
+
ex = ExampleRecord.new( :name => "exemplar" )
|
133
|
+
ex.should be_valid
|
134
|
+
ex.state_fu_field.should == nil
|
135
|
+
ex.save!
|
136
|
+
ex.should_not be_new_record
|
137
|
+
ex.state_fu_field.should == 'initial'
|
138
|
+
ex.state_fu.state.name.should == :initial
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should update the field after a transition is completed" do
|
142
|
+
ex = ExampleRecord.create!( :name => "exemplar" )
|
143
|
+
ex.state_fu.state.name.should == :initial
|
144
|
+
ex.state_fu_field.should == 'initial'
|
145
|
+
t = ex.state_fu.change!
|
146
|
+
t.should be_accepted
|
147
|
+
ex.state_fu.state.name.should == :final
|
148
|
+
ex.state_fu_field.should == 'final'
|
149
|
+
ex.attributes['state_fu_field'].should == 'final'
|
150
|
+
ex.save!
|
151
|
+
end
|
152
|
+
|
153
|
+
describe "a saved record whose state is not the default" do
|
154
|
+
before do
|
155
|
+
@r = ExampleRecord.create!( :name => "exemplar" )
|
156
|
+
@r.change!
|
157
|
+
@r.state_fu_field.should == 'final'
|
158
|
+
@r.save!
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should be reconstituted with the correct state" do
|
162
|
+
r = ExampleRecord.find( @r.id )
|
163
|
+
r.state_fu.should be_kind_of( StateFu::Binding )
|
164
|
+
r.state_fu.current_state.should be_kind_of( StateFu::State )
|
165
|
+
r.state_fu.current_state.should == ExampleRecord.state_fu_machine.states[:final]
|
166
|
+
end
|
167
|
+
end # saved record after transition
|
168
|
+
|
169
|
+
describe "when a second machine named :status is defined with :field_name => 'status' " do
|
170
|
+
before do
|
171
|
+
ExampleRecord.state_fu_machine(:status, :field_name => 'status') do
|
172
|
+
event( :go, :from => :initial, :to => :final )
|
173
|
+
end
|
174
|
+
@ex = ExampleRecord.new()
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should have a binding for .status" do
|
178
|
+
@ex.status.should be_kind_of( StateFu::Binding )
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should have an ActiveRecord persister with the field_name :status" do
|
182
|
+
@ex.status.persister.should be_kind_of( StateFu::Persistence::ActiveRecord )
|
183
|
+
@ex.status.persister.field_name.should == :status
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should have a value of nil for the status field before state_fu is called" do
|
187
|
+
@ex.read_attribute('status').should be_nil
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should have the ActiveRecord setter method .status=" do
|
191
|
+
@ex.status= 'damp'
|
192
|
+
@ex.read_attribute(:status).should == 'damp'
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should raise StateFu::InvalidState if the status field is set to a bad value and .status is called" do
|
196
|
+
@ex.status= 'damp'
|
197
|
+
lambda { @ex.status }.should raise_error( StateFu::InvalidStateName )
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end # second machine
|
201
|
+
end # with before_create filter
|
202
|
+
end # default machine
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../helper")
|
2
|
+
|
3
|
+
module BenchGrinder
|
4
|
+
def snark
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "extending StateFu::Lathe" do
|
9
|
+
include MySpecHelper
|
10
|
+
|
11
|
+
describe "helpers" do
|
12
|
+
before do
|
13
|
+
reset!
|
14
|
+
make_pristine_class('Klass')
|
15
|
+
@machine = Klass.state_fu_machine() do
|
16
|
+
state :init
|
17
|
+
end
|
18
|
+
end # before
|
19
|
+
|
20
|
+
describe "lathe.helper" do
|
21
|
+
it "should add the arguments to the machine's collection of helpers" do
|
22
|
+
@machine.should respond_to(:helpers)
|
23
|
+
@machine.helpers.should be_empty
|
24
|
+
@machine.lathe do
|
25
|
+
helper :bench_grinder
|
26
|
+
end
|
27
|
+
@machine.helpers.should_not be_empty
|
28
|
+
@machine.helpers.should include(:bench_grinder)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should extend the binding with the helper's methods" do
|
32
|
+
@machine.lathe do
|
33
|
+
helper :bench_grinder
|
34
|
+
end
|
35
|
+
@machine.helpers.should include(:bench_grinder)
|
36
|
+
@obj = Klass.new
|
37
|
+
@obj.state_fu.should respond_to(:snark)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require File.expand_path("#{File.dirname(__FILE__)}/../helper")
|
2
|
+
|
3
|
+
|
4
|
+
##
|
5
|
+
##
|
6
|
+
##
|
7
|
+
|
8
|
+
describe "A pristine class Klass with StateFu included:" do
|
9
|
+
include MySpecHelper
|
10
|
+
before(:each) do
|
11
|
+
make_pristine_class 'Klass'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return a new Machine bound to the class given Klass.state_fu_machine()" do
|
15
|
+
Klass.should respond_to(:state_fu_machine)
|
16
|
+
Klass.state_fu_machine.should be_kind_of(StateFu::Machine)
|
17
|
+
machine = Klass.state_fu_machine
|
18
|
+
Klass.state_fu_machine.should == machine
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return {} given Klass.state_fu_machines" do
|
22
|
+
Klass.should respond_to(:state_fu_machines)
|
23
|
+
Klass.state_fu_machines.should == {}
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
##
|
28
|
+
##
|
29
|
+
|
30
|
+
describe "Having called Klass.state_fu_machine() with an empty block:" do
|
31
|
+
before(:each) do
|
32
|
+
Klass.state_fu_machine do
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should return a StateFu::Machine given Klass.state_fu_machine()" do
|
37
|
+
Klass.should respond_to(:state_fu_machine)
|
38
|
+
Klass.state_fu_machine.should_not be_nil
|
39
|
+
Klass.state_fu_machine.should be_kind_of( StateFu::Machine )
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return { :default => <StateFu::Machine> } given Klass.state_fu_machines()" do
|
43
|
+
Klass.should respond_to(:state_fu_machines)
|
44
|
+
machines = Klass.state_fu_machines()
|
45
|
+
machines.should be_kind_of(Hash)
|
46
|
+
machines.should_not be_empty
|
47
|
+
machines.length.should == 1
|
48
|
+
machines.keys.should == [StateFu::DEFAULT]
|
49
|
+
machines.values.first.should be_kind_of( StateFu::Machine )
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "Having called Klass.state_fu_machine(:two) with an empty block:" do
|
53
|
+
before(:each) do
|
54
|
+
Klass.state_fu_machine(:two) do
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return a StateFu::Machine given Klass.state_fu_machine(:two)" do
|
59
|
+
Klass.should respond_to(:state_fu_machine)
|
60
|
+
Klass.state_fu_machine(:two).should_not be_nil
|
61
|
+
Klass.state_fu_machine(:two).should be_kind_of( StateFu::Machine )
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should return a new Machine given Klass.state_fu_machine(:three)" do
|
65
|
+
Klass.should respond_to(:state_fu_machine)
|
66
|
+
Klass.state_fu_machine(:three).should be_kind_of( StateFu::Machine )
|
67
|
+
three = Klass.state_fu_machine(:three)
|
68
|
+
Klass.state_fu_machines[:three].should == three
|
69
|
+
Klass.state_fu_machine(:three).should == three
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should return { :default => <StateFu::Machine>, :two => <StateFu::Machine> } given Klass.state_fu_machines()" do
|
73
|
+
Klass.should respond_to(:state_fu_machines)
|
74
|
+
machines = Klass.state_fu_machines()
|
75
|
+
machines.should be_kind_of(Hash)
|
76
|
+
machines.should_not be_empty
|
77
|
+
machines.length.should == 2
|
78
|
+
machines.keys.should include StateFu::DEFAULT
|
79
|
+
machines.keys.should include :two
|
80
|
+
machines.values.length.should == 2
|
81
|
+
machines.values.each { |v| v.should be_kind_of( StateFu::Machine ) }
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should return [DEFAULT, :two] give Klass.state_fu_machines.keys" do
|
85
|
+
Klass.should respond_to(:state_fu_machines)
|
86
|
+
Klass.state_fu_machines.keys.should =~ [StateFu::DEFAULT, :two]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "An empty class Child which inherits from Klass" do
|
91
|
+
before() do
|
92
|
+
Object.send(:remove_const, 'Child' ) if Object.const_defined?( 'Child' )
|
93
|
+
class Child < Klass
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# sorry, Lamarckism not supported
|
98
|
+
it "does NOT inherit it's parent class' Machines !!" do
|
99
|
+
Child.state_fu_machine.should_not == Klass.state_fu_machine
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should know the Machine after calling Klass.state_fu_machine.bind!( Child )" do
|
103
|
+
Child.state_fu_machine.should_not == Klass.state_fu_machine
|
104
|
+
Klass.state_fu_machine.bind!( Child )
|
105
|
+
Klass.state_fu_machines.should == { StateFu::DEFAULT => Klass.state_fu_machine }
|
106
|
+
Child.state_fu_machine.should == Klass.state_fu_machine
|
107
|
+
Klass.state_fu_machine.bind!( Child, :snoo )
|
108
|
+
Child.state_fu_machines.should == {
|
109
|
+
StateFu::DEFAULT => Klass.state_fu_machine,
|
110
|
+
:snoo => Klass.state_fu_machine
|
111
|
+
}
|
112
|
+
Child.state_fu_machine(:snoo).should == Klass.state_fu_machine
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|