forked from mattetti/couchrest
/
property_spec.rb
263 lines (222 loc) · 8.49 KB
/
property_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
require File.expand_path('../../../spec_helper', __FILE__)
require File.join(FIXTURE_PATH, 'more', 'person')
require File.join(FIXTURE_PATH, 'more', 'card')
require File.join(FIXTURE_PATH, 'more', 'invoice')
require File.join(FIXTURE_PATH, 'more', 'service')
require File.join(FIXTURE_PATH, 'more', 'event')
require File.join(FIXTURE_PATH, 'more', 'cat')
describe "ExtendedDocument properties" do
before(:each) do
reset_test_db!
@card = Card.new(:first_name => "matt")
end
it "should be accessible from the object" do
@card.properties.should be_an_instance_of(Array)
@card.properties.map{|p| p.name}.should include("first_name")
end
it "should let you access a property value (getter)" do
@card.first_name.should == "matt"
end
it "should let you set a property value (setter)" do
@card.last_name = "Aimonetti"
@card.last_name.should == "Aimonetti"
end
it "should not let you set a property value if it's read only" do
lambda{@card.read_only_value = "test"}.should raise_error
end
it "should let you use an alias for an attribute" do
@card.last_name = "Aimonetti"
@card.family_name.should == "Aimonetti"
@card.family_name.should == @card.last_name
end
it "should let you use an alias for a casted attribute" do
@card.cast_alias = Person.new(:name => "Aimonetti")
@card.cast_alias.name.should == "Aimonetti"
@card.calias.name.should == "Aimonetti"
card = Card.new(:first_name => "matt", :cast_alias => {:name => "Aimonetti"})
card.cast_alias.name.should == "Aimonetti"
card.calias.name.should == "Aimonetti"
end
it "should be auto timestamped" do
@card.created_at.should be_nil
@card.updated_at.should be_nil
@card.save.should be_true
@card.created_at.should_not be_nil
@card.updated_at.should_not be_nil
end
describe "validation" do
before(:each) do
@invoice = Invoice.new(:client_name => "matt", :employee_name => "Chris", :location => "San Diego, CA")
end
it "should be able to be validated" do
@card.valid?.should == true
end
it "should let you validate the presence of an attribute" do
@card.first_name = nil
@card.should_not be_valid
@card.errors.should_not be_empty
@card.errors.on(:first_name).should == ["First name must not be blank"]
end
it "should let you look up errors for a field by a string name" do
@card.first_name = nil
@card.should_not be_valid
@card.errors.on('first_name').should == ["First name must not be blank"]
end
it "should validate the presence of 2 attributes" do
@invoice.clear
@invoice.should_not be_valid
@invoice.errors.should_not be_empty
@invoice.errors.on(:client_name).first.should == "Client name must not be blank"
@invoice.errors.on(:employee_name).should_not be_empty
end
it "should let you set an error message" do
@invoice.location = nil
@invoice.valid?
@invoice.errors.on(:location).should == ["Hey stupid!, you forgot the location"]
end
it "should validate before saving" do
@invoice.location = nil
@invoice.should_not be_valid
@invoice.save.should be_false
@invoice.should be_new
end
end
describe "autovalidation" do
before(:each) do
@service = Service.new(:name => "Coumpound analysis", :price => 3_000)
end
it "should be valid" do
@service.should be_valid
end
it "should not respond to properties not setup" do
@service.respond_to?(:client_name).should be_false
end
describe "property :name, :length => 4...20" do
it "should autovalidate the presence when length is set" do
@service.name = nil
@service.should_not be_valid
@service.errors.should_not be_nil
@service.errors.on(:name).first.should == "Name must be between 4 and 19 characters long"
end
it "should autovalidate the correct length" do
@service.name = "a"
@service.should_not be_valid
@service.errors.should_not be_nil
@service.errors.on(:name).first.should == "Name must be between 4 and 19 characters long"
end
end
end
describe "casting" do
describe "cast keys to any type" do
before(:all) do
event_doc = { :subject => "Some event", :occurs_at => Time.now, :end_date => Date.today }
e = Event.database.save_doc event_doc
@event = Event.get e['id']
end
it "should cast occurs_at to Time" do
@event['occurs_at'].should be_an_instance_of(Time)
end
it "should cast end_date to Date" do
@event['end_date'].should be_an_instance_of(Date)
end
end
describe "casting to Float object" do
class RootBeerFloat < CouchRest::ExtendedDocument
use_database DB
property :price, :cast_as => 'Float'
end
it "should convert a string into a float if casted as so" do
RootBeerFloat.new(:price => '12.50').price.should == 12.50
RootBeerFloat.new(:price => '9').price.should == 9.0
RootBeerFloat.new(:price => '-9').price.should == -9.0
end
it "should not convert a string if it's not a string that can be cast as a float" do
RootBeerFloat.new(:price => 'test').price.should == 'test'
end
it "should work fine when a float is being passed" do
RootBeerFloat.new(:price => 9.99).price.should == 9.99
end
end
describe "casting to a boolean value" do
class RootBeerFloat < CouchRest::ExtendedDocument
use_database DB
property :tasty, :cast_as => :boolean
end
it "should add an accessor with a '?' for boolean attributes that returns true or false" do
RootBeerFloat.new(:tasty => true).tasty?.should == true
RootBeerFloat.new(:tasty => 'you bet').tasty?.should == true
RootBeerFloat.new(:tasty => 123).tasty?.should == true
RootBeerFloat.new(:tasty => false).tasty?.should == false
RootBeerFloat.new(:tasty => 'false').tasty?.should == false
RootBeerFloat.new(:tasty => 'FaLsE').tasty?.should == false
RootBeerFloat.new(:tasty => nil).tasty?.should == false
end
it "should return the real value when the default accessor is used" do
RootBeerFloat.new(:tasty => true).tasty.should == true
RootBeerFloat.new(:tasty => 'you bet').tasty.should == 'you bet'
RootBeerFloat.new(:tasty => 123).tasty.should == 123
RootBeerFloat.new(:tasty => 'false').tasty.should == 'false'
RootBeerFloat.new(:tasty => false).tasty.should == false
RootBeerFloat.new(:tasty => nil).tasty.should == nil
end
end
end
end
describe "a newly created casted model" do
before(:each) do
reset_test_db!
@cat = Cat.new(:name => 'Toonces')
@squeaky_mouse = CatToy.new(:name => 'Squeaky')
end
describe "assigned assigned to a casted property" do
it "should have casted_by set to its parent" do
@squeaky_mouse.casted_by.should be_nil
@cat.favorite_toy = @squeaky_mouse
@squeaky_mouse.casted_by.should === @cat
end
end
describe "appended to a casted collection" do
it "should have casted_by set to its parent" do
@squeaky_mouse.casted_by.should be_nil
@cat.toys << @squeaky_mouse
@squeaky_mouse.casted_by.should === @cat
@cat.save
@cat.toys.first.casted_by.should === @cat
end
end
describe "list assigned to a casted collection" do
it "should have casted_by set on all elements" do
toy1 = CatToy.new(:name => 'Feather')
toy2 = CatToy.new(:name => 'Mouse')
@cat.toys = [toy1, toy2]
toy1.casted_by.should === @cat
toy2.casted_by.should === @cat
@cat.save
@cat = Cat.get(@cat.id)
@cat.toys[0].casted_by.should === @cat
@cat.toys[1].casted_by.should === @cat
end
end
end
describe "a casted model retrieved from the database" do
before(:each) do
reset_test_db!
@cat = Cat.new(:name => 'Stimpy')
@cat.favorite_toy = CatToy.new(:name => 'Stinky')
@cat.toys << CatToy.new(:name => 'Feather')
@cat.toys << CatToy.new(:name => 'Mouse')
@cat.save
@cat = Cat.get(@cat.id)
end
describe "as a casted property" do
it "should already be casted_by its parent" do
@cat.favorite_toy.casted_by.should === @cat
end
end
describe "from a casted collection" do
it "should already be casted_by its parent" do
@cat.toys[0].casted_by.should === @cat
@cat.toys[1].casted_by.should === @cat
end
end
end