maintain 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,67 @@
1
+ # Some specs to check against ActiveRecord conflicts. Rails tends to blow
2
+ # shit up when you build it outside of Rails. We'll see how this goes...
3
+
4
+ proceed = false
5
+ begin
6
+ require 'rubygems'
7
+ require 'active_record'
8
+ proceed = true
9
+ rescue LoadError
10
+ puts 'Not testing ActiveRecord (unavailable)'
11
+ end
12
+
13
+ if proceed
14
+ # Use load to have it evaluate the ActiveRecord::Base extension logic again, in the event
15
+ # that we've already done that with a previous test.
16
+ load 'lib/maintain.rb'
17
+ describe Maintain, "ActiveRecord::Base" do
18
+ it "should automatically be extended" do
19
+ ActiveRecord::Base.should respond_to(:maintain)
20
+ end
21
+ describe "accessors" do
22
+ before :each do
23
+ ActiveRecord::Base.establish_connection({:adapter => 'sqlite3', :database => ':memory:', :pool => 5, :timeout => 5000})
24
+ class ActiveMaintainTest < ActiveRecord::Base; end
25
+ silence_stream(STDOUT) do
26
+ ActiveRecord::Schema.define do
27
+ create_table :active_maintain_tests, :force => true do |t|
28
+ t.string :status
29
+ end
30
+ end
31
+ end
32
+
33
+ ActiveMaintainTest.maintain :status do
34
+ state :new, :default => true
35
+ state :old
36
+ aggregate :everything, :as => [:new, :old]
37
+ end
38
+ end
39
+
40
+ it "should default to 'new'" do
41
+ ActiveMaintainTest.new.status.should == 'new'
42
+ ActiveMaintainTest.new.status.should == :new
43
+ end
44
+
45
+ it "should allow us to update its status to 'old'" do
46
+ active_maintain_test = ActiveMaintainTest.new(:status => 'old')
47
+ active_maintain_test.status.should == 'old'
48
+ lambda {
49
+ active_maintain_test.save!
50
+ }.should_not raise_error
51
+ ActiveMaintainTest.first.status.should == 'old'
52
+ end
53
+ end
54
+
55
+ describe "named_scopes" do
56
+ it "should create named_scopes for all states" do
57
+ ActiveMaintainTest.should respond_to(:old)
58
+ ActiveMaintainTest.old.should be_instance_of(Array)
59
+ end
60
+
61
+ it "should create named_scopes for all aggregates" do
62
+ ActiveMaintainTest.should respond_to(:everything)
63
+ ActiveMaintainTest.everything.should be_instance_of(Array)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,35 @@
1
+ # Configuration point number one: setting and configuring states
2
+
3
+ require 'lib/maintain'
4
+
5
+ describe Maintain, "aggregates" do
6
+ before :each do
7
+ class MaintainTest
8
+ extend Maintain
9
+ end
10
+ end
11
+
12
+ it "should allow me to define an aggregate" do
13
+ lambda {
14
+ MaintainTest.maintains :state do
15
+ state :old
16
+ state :new
17
+ state :borrowed
18
+ state :blue
19
+ aggregate :b_words, [:borrowed, :blue]
20
+ end
21
+ }.should_not raise_error
22
+ end
23
+
24
+ it "should create boolean methods" do
25
+ MaintainTest.new.should respond_to(:b_words?)
26
+ end
27
+
28
+ it "should return true if one of the states is met in the boolean" do
29
+ maintain = MaintainTest.new
30
+ maintain.state = :new
31
+ maintain.b_words?.should be_false
32
+ maintain.state = :blue
33
+ maintain.b_words?.should be_true
34
+ end
35
+ end
@@ -0,0 +1,83 @@
1
+ # Basic class method specs
2
+
3
+ require 'lib/maintain'
4
+
5
+ describe Maintain do
6
+ before :each do
7
+ class MaintainTest
8
+ extend Maintain
9
+ end
10
+ end
11
+
12
+ describe "bitmask" do
13
+ before :each do
14
+ MaintainTest.maintain :permissions, :bitmask => true do
15
+ state :edit, 1
16
+ state :delete, 2
17
+ state :update, 3
18
+ end
19
+ @maintainer = MaintainTest.new
20
+ end
21
+
22
+ describe "accessor methods" do
23
+ it "should default to zero" do
24
+ maintainer = MaintainTest.new
25
+ maintainer.permissions.should == 0
26
+ end
27
+
28
+ it "should be able to test values" do
29
+ maintainer = MaintainTest.new
30
+ maintainer.permissions = :edit
31
+ maintainer.permissions.edit?.should be_true
32
+ maintainer.permissions.delete?.should_not be_true
33
+ maintainer.permissions = [:update, :delete]
34
+ maintainer.permissions.edit?.should_not be_true
35
+ maintainer.permissions.delete?.should be_true
36
+ maintainer.permissions.update?.should be_true
37
+ end
38
+
39
+ it "should be able to test values directly on the class" do
40
+ maintainer = MaintainTest.new
41
+ maintainer.permissions = :edit
42
+ maintainer.edit?.should be_true
43
+ maintainer.delete?.should_not be_true
44
+ end
45
+
46
+ it "should not trap every method" do
47
+ maintainer = MaintainTest.new
48
+ lambda {
49
+ maintainer.permissions.foobar?
50
+ }.should raise_error(NoMethodError)
51
+ end
52
+ end
53
+
54
+ describe "setter methods" do
55
+ it "should be able to set values on the whole field" do
56
+ @maintainer.permissions = :edit
57
+ @maintainer.permissions.should == [:edit]
58
+ @maintainer.permissions.should == 2
59
+ end
60
+
61
+ it "should be able to set values as an array" do
62
+ @maintainer.permissions = [:edit, :delete]
63
+ @maintainer.permissions.should == 6
64
+ @maintainer.permissions.should_not == 7
65
+ @maintainer.permissions.should == [:edit, :delete]
66
+ end
67
+
68
+ it "should be able to set individual bitmask values" do
69
+ @maintainer.permissions = nil
70
+ @maintainer.permissions = []
71
+ @maintainer.permissions.should == 0
72
+ @maintainer.permissions.edit!
73
+ @maintainer.permissions.edit?.should be_true
74
+ @maintainer.permissions.delete?.should_not be_true
75
+ @maintainer.permissions.update!
76
+ @maintainer.permissions.edit?.should be_true
77
+ @maintainer.permissions.edit?.should be_true
78
+ @maintainer.permissions.delete?.should_not be_true
79
+ @maintainer.permissions.update?.should be_true
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,194 @@
1
+ # Comparing state values
2
+
3
+ require 'lib/maintain'
4
+
5
+ describe Maintain do
6
+ before :each do
7
+ class MaintainTest
8
+ attr_accessor :existant_attribute
9
+ extend Maintain
10
+ end
11
+ end
12
+
13
+ describe "testing" do
14
+ describe "string states" do
15
+ before :each do
16
+ MaintainTest.maintain :state, :default => :new do
17
+ state :new
18
+ state :overdue
19
+ state :closed
20
+ end
21
+ @maintainer = MaintainTest.new
22
+ @other_maintainer = MaintainTest.new
23
+ end
24
+
25
+ it "equality methods" do
26
+ @maintainer.state.should == :new
27
+ @maintainer.state.should == 'new'
28
+ @maintainer.state.should == 0
29
+ @maintainer.state.should == MaintainTest.new.state
30
+ @maintainer.state.should == @other_maintainer.state
31
+ end
32
+
33
+ describe "boolean methods" do
34
+ describe "on the accessor" do
35
+ it "should work" do
36
+ MaintainTest.maintain :state, :default => :new do
37
+ state :new
38
+ state :overdue
39
+ state :closed
40
+ end
41
+ maintainer = MaintainTest.new
42
+ maintainer.state.new?.should be_true
43
+ maintainer.state.overdue?.should be_false
44
+ maintainer.state.closed?.should be_false
45
+ end
46
+
47
+ it "should not trap every method" do
48
+ maintainer = MaintainTest.new
49
+ lambda {
50
+ maintainer.permissions.foobar?
51
+ }.should raise_error(NoMethodError)
52
+ end
53
+ end
54
+
55
+ describe "on the class itself" do
56
+ it "should work, too" do
57
+ MaintainTest.maintain :state, :default => :new do
58
+ state :new
59
+ state :overdue
60
+ state :closed
61
+ end
62
+ maintainer = MaintainTest.new
63
+ maintainer.state.new?.should be_true
64
+ maintainer.state.overdue?.should be_false
65
+ maintainer.state.closed?.should be_false
66
+ end
67
+
68
+ it "should not override pre-existing methods" do
69
+ class MaintainTestTwo
70
+ def new?
71
+ :i_existed_before_you_came_along
72
+ end
73
+ extend Maintain
74
+ maintains :state, :default => :new do
75
+ state :new
76
+ state :overdue
77
+ state :closed
78
+ end
79
+ end
80
+ MaintainTestTwo.new.new?.should == :i_existed_before_you_came_along
81
+ end
82
+ end
83
+ end
84
+
85
+ it "greater than method" do
86
+ MaintainTest.maintain :state, :default => :closed do
87
+ state :new
88
+ state :overdue
89
+ state :closed
90
+ end
91
+ @maintainer.state.should be > :overdue
92
+ @maintainer.state.should be > 'overdue'
93
+ @maintainer.state.should be > 1
94
+ end
95
+
96
+ it "less than method" do
97
+ @maintainer.state.should be < :overdue
98
+ @maintainer.state.should be < 'overdue'
99
+ @maintainer.state.should be < 1
100
+ end
101
+
102
+ it "greater-than-or-equal-to method" do
103
+ MaintainTest.maintain :state, :default => :closed do
104
+ state :new
105
+ state :overdue
106
+ state :closed
107
+ end
108
+ @maintainer.state.should be >= :overdue
109
+ @maintainer.state.should be >= 'overdue'
110
+ @maintainer.state.should be >= 1
111
+ @maintainer.state.should be >= :closed
112
+ @maintainer.state.should be >= 'closed'
113
+ @maintainer.state.should be >= 2
114
+ end
115
+
116
+ it "less-than-or-equal-to method" do
117
+ MaintainTest.maintain :state, :default => :new do
118
+ state :new
119
+ state :overdue
120
+ state :closed
121
+ end
122
+ @maintainer.state.should be <= :overdue
123
+ @maintainer.state.should be <= 'overdue'
124
+ @maintainer.state.should be <= 1
125
+ @maintainer.state.should be <= :new
126
+ @maintainer.state.should be <= 'new'
127
+ @maintainer.state.should be <= 0
128
+ end
129
+ end
130
+
131
+ describe "integer states" do
132
+ before :each do
133
+ MaintainTest.maintain :state, :default => :new do
134
+ state :new, 1
135
+ state :overdue, 2
136
+ state :closed, 3
137
+ end
138
+ @maintainer = MaintainTest.new
139
+ end
140
+
141
+ it "equality methods" do
142
+ @maintainer.state.should == :new
143
+ @maintainer.state.should == 'new'
144
+ @maintainer.state.should == 1
145
+ @maintainer.state.should == MaintainTest.new.state
146
+ end
147
+
148
+ it "greater than method" do
149
+ MaintainTest.maintain :state, :default => :closed do
150
+ state :new, 1
151
+ state :overdue, 2
152
+ state :closed, 3
153
+ end
154
+ @maintainer.state.should be > :overdue
155
+ @maintainer.state.should be > 'overdue'
156
+ @maintainer.state.should be > 1
157
+ end
158
+
159
+ it "less than method" do
160
+ @maintainer.state.should be < :overdue
161
+ @maintainer.state.should be < 'overdue'
162
+ @maintainer.state.should be < 2
163
+ end
164
+
165
+ it "greater-than-or-equal-to method" do
166
+ MaintainTest.maintain :state, :default => :closed do
167
+ state :new, 1
168
+ state :overdue, 2
169
+ state :closed, 3
170
+ end
171
+ @maintainer.state.should be >= :overdue
172
+ @maintainer.state.should be >= 'overdue'
173
+ @maintainer.state.should be >= 2
174
+ @maintainer.state.should be >= :closed
175
+ @maintainer.state.should be >= 'closed'
176
+ @maintainer.state.should be >= 3
177
+ end
178
+
179
+ it "less-than-or-equal-to method" do
180
+ MaintainTest.maintain :state, :default => :new do
181
+ state :new, 1
182
+ state :overdue, 2
183
+ state :closed, 3
184
+ end
185
+ @maintainer.state.should be <= :overdue
186
+ @maintainer.state.should be <= 'overdue'
187
+ @maintainer.state.should be <= 2
188
+ @maintainer.state.should be <= :new
189
+ @maintainer.state.should be <= 'new'
190
+ @maintainer.state.should be <= 1
191
+ end
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,79 @@
1
+ # Configuration point number one: setting and configuring states
2
+
3
+ require 'lib/maintain'
4
+
5
+ describe Maintain do
6
+ before :each do
7
+ class MaintainTest
8
+ attr_accessor :existant_attribute
9
+ extend Maintain
10
+ end
11
+ end
12
+
13
+ describe "defining states" do
14
+ it "should be possible" do
15
+ lambda {
16
+ MaintainTest.maintain :existant_attribute do
17
+ state :new
18
+ end
19
+ }.should_not raise_error
20
+ MaintainTest.new.existant_attribute.should be_nil
21
+ end
22
+
23
+ it "should support default values" do
24
+ MaintainTest.maintain :existant_attribute do
25
+ state :new, :default => true
26
+ end
27
+ MaintainTest.new.existant_attribute.should == :new
28
+ end
29
+
30
+ it "should support integer values" do
31
+ MaintainTest.maintain :existant_attribute do
32
+ state :new, 1, :default => true
33
+ end
34
+ MaintainTest.new.existant_attribute.should == 1
35
+ end
36
+
37
+ it "should provide accessor methods on the Maintain::Maintainer class for state values" do
38
+ maintainer = MaintainTest.maintain :permissions, :bitmask => true do
39
+ state :edit, 1
40
+ state :delete, 2
41
+ state :update, 3
42
+ end
43
+ maintainer.update.should == 8
44
+ end
45
+
46
+ it "should not trap all methods when providing accessor methods for state values" do
47
+ maintainer = MaintainTest.maintain :permissions, :bitmask => true do
48
+ state :edit, 1
49
+ state :delete, 2
50
+ state :update, 3
51
+ end
52
+ lambda {
53
+ maintainer.i_probably_dont_exist
54
+ }.should raise_error(NoMethodError)
55
+ end
56
+
57
+ describe "as bitmask" do
58
+ it "should calculate a base-2 compatible integer" do
59
+ maintainer = MaintainTest.maintain :permissions, :bitmask => true do
60
+ state :edit, 1
61
+ state :delete, 2
62
+ state :update, 3
63
+ end
64
+ maintainer.update.should == 8
65
+ end
66
+
67
+ it "should auto-increment bitmask column values (but dangerously!)" do
68
+ maintainer = MaintainTest.maintain :permissions, :bitmask => true do
69
+ state :edit
70
+ state :delete
71
+ state :update
72
+ end
73
+ maintainer.edit.should == 1
74
+ maintainer.delete.should == 2
75
+ maintainer.update.should == 4
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,44 @@
1
+ # Comparing state values
2
+
3
+ require 'lib/maintain'
4
+
5
+ describe Maintain, "hooks" do
6
+ before :each do
7
+ class MaintainTest
8
+ extend Maintain
9
+ end
10
+ end
11
+
12
+ it "should allow me to hook into entry and exit" do
13
+ lambda {
14
+ MaintainTest.maintain :state do
15
+ state :new, :enter => :new_entered
16
+ state :old, :enter => :old_entered
17
+ on :enter, :new, :new_entered
18
+ on :exit, :old do
19
+ self.old_entered
20
+ end
21
+ end
22
+ }.should_not raise_error
23
+ end
24
+
25
+ it "should execute hooks when states are entered and exited" do
26
+ MaintainTest.maintain :state do
27
+ state :new
28
+ state :old
29
+ on :enter, :new, :new_entered
30
+ on :exit, :old do
31
+ self.old_entered
32
+ end
33
+ end
34
+
35
+ maintain = MaintainTest.new
36
+ maintain.should_receive(:new_entered)
37
+ maintain.state = :new
38
+ maintain.should_receive(:old_entered)
39
+ maintain.state = :old
40
+ maintain.should_not_receive(:old_entered)
41
+ maintain.state = :old
42
+ end
43
+
44
+ end
@@ -0,0 +1,22 @@
1
+ # Basic class method specs
2
+
3
+ require 'lib/maintain'
4
+
5
+ describe Maintain do
6
+ before :each do
7
+ class MaintainTest
8
+ extend Maintain
9
+ end
10
+ end
11
+
12
+ describe "integer" do
13
+ before :each do
14
+ MaintainTest.maintain :kind, :integer => true do
15
+ state :man, 1
16
+ state :woman, 2
17
+ state :none, 3
18
+ end
19
+ @maintainer = MaintainTest.new
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,45 @@
1
+ # Basic class method specs
2
+
3
+ require 'lib/maintain'
4
+
5
+ describe Maintain do
6
+ before :each do
7
+ class MaintainTest
8
+ attr_accessor :existant_attribute
9
+ extend Maintain
10
+ end
11
+ end
12
+
13
+ # Basic overview / class methods
14
+ it "should extend things that include it" do
15
+ MaintainTest.should respond_to(:maintains)
16
+ end
17
+
18
+ it "should alias the maintain method as `maintains`" do
19
+ MaintainTest.should respond_to(:maintains)
20
+ end
21
+
22
+ it "should accept a block" do
23
+ lambda {
24
+ MaintainTest.maintain :non_existant_attribute do
25
+
26
+ end
27
+ }.should_not raise_error
28
+ end
29
+
30
+ it "should store a reference to all of the defined states in the class" do
31
+ MaintainTest.maintain :non_existant_attribute
32
+ MaintainTest.send(:maintainers)[:non_existant_attribute].should be_instance_of(Maintain::Maintainer)
33
+ end
34
+
35
+ it "should define accessors for non-existant attributes" do
36
+ MaintainTest.maintain :non_existant_attribute
37
+ MaintainTest.new.should respond_to('non_existant_attribute', 'non_existant_attribute=')
38
+ end
39
+
40
+ it "shouldn't care about existant attributes" do
41
+ lambda {
42
+ MaintainTest.maintain :existant_attribute
43
+ }.should_not raise_error
44
+ end
45
+ end
@@ -0,0 +1,7 @@
1
+ describe 'Maintain' do
2
+ it "should not monkey patch Object" do
3
+ lambda {
4
+ require "lib/maintain"
5
+ }.should_not change(Object, :methods)
6
+ end
7
+ end
@@ -0,0 +1,124 @@
1
+ # Comparing state values
2
+
3
+ require 'lib/maintain'
4
+
5
+ describe Maintain do
6
+ before :each do
7
+ class MaintainTest
8
+ attr_accessor :existant_attribute
9
+ extend Maintain
10
+ end
11
+
12
+ end
13
+
14
+ describe "`class` calls" do
15
+ it "should return NilClass for states without a value" do
16
+ MaintainTest.maintain :state do
17
+ state :new
18
+ state :overdue
19
+ state :closed
20
+ end
21
+ MaintainTest.new.state.class.should == NilClass
22
+ end
23
+
24
+ it "should return Symbol for states with a string column" do
25
+ MaintainTest.maintain :state do
26
+ state :new
27
+ state :overdue
28
+ state :closed
29
+ end
30
+ maintain_test = MaintainTest.new
31
+ maintain_test.state = :overdue
32
+ maintain_test.state.class.should == Symbol
33
+ end
34
+
35
+ it "should return Integer for states with an integer column" do
36
+ MaintainTest.maintain :state do
37
+ state :new, 0
38
+ state :overdue, 1
39
+ state :closed, 2
40
+ end
41
+ maintain_test = MaintainTest.new
42
+ maintain_test.state = :closed
43
+ maintain_test.state.class.should == Fixnum
44
+ end
45
+ end
46
+
47
+ describe "`inspect` calls" do
48
+ it "should return 'nil' for states without a default" do
49
+ MaintainTest.maintain :state do
50
+ state :new
51
+ state :overdue
52
+ state :closed
53
+ end
54
+ MaintainTest.new.state.inspect.should == 'nil'
55
+ end
56
+
57
+ it "should return ':new' for a state with a default value of :new" do
58
+ MaintainTest.maintain :state, :default => :new do
59
+ state :new
60
+ state :overdue
61
+ state :closed
62
+ end
63
+ MaintainTest.new.state.inspect.should == ':new'
64
+ end
65
+
66
+ it "should return '2' for a state with a default value of :new, 2 and an :integer column" do
67
+ MaintainTest.maintain :state, :default => :new do
68
+ state :new, 2
69
+ state :overdue, 5
70
+ state :closed, 22
71
+ end
72
+ MaintainTest.new.state.inspect.should == '2'
73
+ end
74
+ end
75
+
76
+ describe "`nil?` calls" do
77
+ it "should return true for states without a default" do
78
+ MaintainTest.maintain :state do
79
+ state :new
80
+ state :overdue
81
+ state :closed
82
+ end
83
+ MaintainTest.new.state.nil?.should be_true
84
+ end
85
+
86
+ it "should return false for states with a default" do
87
+ MaintainTest.maintain :state, :default => :new do
88
+ state :new
89
+ state :overdue
90
+ state :closed
91
+ end
92
+ MaintainTest.new.state.nil?.should_not be_true
93
+ end
94
+ end
95
+
96
+ describe "`to_s` calls" do
97
+ it "should return '' for states without a default" do
98
+ MaintainTest.maintain :state do
99
+ state :new
100
+ state :overdue
101
+ state :closed
102
+ end
103
+ MaintainTest.new.state.to_s.should == ''
104
+ end
105
+
106
+ it "should return 'new' for a state with a default value of :new" do
107
+ MaintainTest.maintain :state, :default => :new do
108
+ state :new
109
+ state :overdue
110
+ state :closed
111
+ end
112
+ MaintainTest.new.state.to_s.should == 'new'
113
+ end
114
+
115
+ it "should return '2' for a state with a default value of :new, 2 and an :integer column" do
116
+ MaintainTest.maintain :state, :default => :new do
117
+ state :new, 2
118
+ state :overdue, 5
119
+ state :closed, 22
120
+ end
121
+ MaintainTest.new.state.to_s.should == '2'
122
+ end
123
+ end
124
+ end