davber_couch_potato 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.
- data/CHANGES.md +106 -0
- data/MIT-LICENSE.txt +19 -0
- data/README.md +409 -0
- data/VERSION.yml +5 -0
- data/init.rb +3 -0
- data/lib/core_ext/date.rb +21 -0
- data/lib/core_ext/object.rb +5 -0
- data/lib/core_ext/string.rb +8 -0
- data/lib/core_ext/symbol.rb +15 -0
- data/lib/core_ext/time.rb +21 -0
- data/lib/couch_potato/database.rb +161 -0
- data/lib/couch_potato/persistence/active_model_compliance.rb +44 -0
- data/lib/couch_potato/persistence/attachments.rb +31 -0
- data/lib/couch_potato/persistence/callbacks.rb +62 -0
- data/lib/couch_potato/persistence/dirty_attributes.rb +56 -0
- data/lib/couch_potato/persistence/ghost_attributes.rb +22 -0
- data/lib/couch_potato/persistence/json.rb +46 -0
- data/lib/couch_potato/persistence/magic_timestamps.rb +20 -0
- data/lib/couch_potato/persistence/properties.rb +86 -0
- data/lib/couch_potato/persistence/simple_property.rb +72 -0
- data/lib/couch_potato/persistence/type_caster.rb +40 -0
- data/lib/couch_potato/persistence.rb +105 -0
- data/lib/couch_potato/railtie.rb +18 -0
- data/lib/couch_potato/rspec/matchers/json2.js +482 -0
- data/lib/couch_potato/rspec/matchers/list_as_matcher.rb +54 -0
- data/lib/couch_potato/rspec/matchers/map_to_matcher.rb +49 -0
- data/lib/couch_potato/rspec/matchers/print_r.js +60 -0
- data/lib/couch_potato/rspec/matchers/reduce_to_matcher.rb +50 -0
- data/lib/couch_potato/rspec/matchers.rb +39 -0
- data/lib/couch_potato/rspec/stub_db.rb +46 -0
- data/lib/couch_potato/rspec.rb +2 -0
- data/lib/couch_potato/validation/with_active_model.rb +27 -0
- data/lib/couch_potato/validation/with_validatable.rb +37 -0
- data/lib/couch_potato/validation.rb +16 -0
- data/lib/couch_potato/view/base_view_spec.rb +67 -0
- data/lib/couch_potato/view/custom_view_spec.rb +42 -0
- data/lib/couch_potato/view/custom_views.rb +52 -0
- data/lib/couch_potato/view/lists.rb +23 -0
- data/lib/couch_potato/view/model_view_spec.rb +75 -0
- data/lib/couch_potato/view/properties_view_spec.rb +47 -0
- data/lib/couch_potato/view/raw_view_spec.rb +25 -0
- data/lib/couch_potato/view/view_query.rb +78 -0
- data/lib/couch_potato.rb +79 -0
- data/rails/init.rb +4 -0
- data/rails/reload_classes.rb +47 -0
- data/spec/attachments_spec.rb +23 -0
- data/spec/callbacks_spec.rb +308 -0
- data/spec/create_spec.rb +34 -0
- data/spec/custom_view_spec.rb +239 -0
- data/spec/default_property_spec.rb +38 -0
- data/spec/destroy_spec.rb +29 -0
- data/spec/fixtures/address.rb +10 -0
- data/spec/fixtures/person.rb +6 -0
- data/spec/property_spec.rb +315 -0
- data/spec/rails_spec.rb +51 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/unit/active_model_compliance_spec.rb +98 -0
- data/spec/unit/attributes_spec.rb +125 -0
- data/spec/unit/base_view_spec_spec.rb +73 -0
- data/spec/unit/callbacks_spec.rb +72 -0
- data/spec/unit/couch_potato_spec.rb +39 -0
- data/spec/unit/create_spec.rb +58 -0
- data/spec/unit/custom_views_spec.rb +15 -0
- data/spec/unit/database_spec.rb +266 -0
- data/spec/unit/date_spec.rb +22 -0
- data/spec/unit/dirty_attributes_spec.rb +166 -0
- data/spec/unit/json_create_id_spec.rb +14 -0
- data/spec/unit/lists_spec.rb +20 -0
- data/spec/unit/model_view_spec_spec.rb +13 -0
- data/spec/unit/properties_view_spec_spec.rb +31 -0
- data/spec/unit/rspec_matchers_spec.rb +124 -0
- data/spec/unit/rspec_stub_db_spec.rb +35 -0
- data/spec/unit/string_spec.rb +7 -0
- data/spec/unit/time_spec.rb +22 -0
- data/spec/unit/validation_spec.rb +67 -0
- data/spec/unit/view_query_spec.rb +78 -0
- data/spec/update_spec.rb +40 -0
- data/spec/view_updates_spec.rb +28 -0
- metadata +205 -0
@@ -0,0 +1,266 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class DbTestUser
|
4
|
+
end
|
5
|
+
|
6
|
+
# namespaced model
|
7
|
+
module Parent
|
8
|
+
class Child
|
9
|
+
include CouchPotato::Persistence
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe CouchPotato::Database, 'new' do
|
14
|
+
it "should raise an exception if the database doesn't exist" do
|
15
|
+
lambda {
|
16
|
+
CouchPotato::Database.new CouchRest.database('couch_potato_invalid')
|
17
|
+
}.should raise_error('Database \'couch_potato_invalid\' does not exist.')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe CouchPotato::Database, 'full_url_to_database' do
|
22
|
+
before(:all) do
|
23
|
+
@database_url = CouchPotato::Config.database_name
|
24
|
+
end
|
25
|
+
|
26
|
+
after(:all) do
|
27
|
+
CouchPotato::Config.database_name = @database_url
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return the full URL when it starts with https" do
|
31
|
+
CouchPotato::Config.database_name = "https://example.com/database"
|
32
|
+
CouchPotato.full_url_to_database.should == 'https://example.com/database'
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return the full URL when it starts with http" do
|
36
|
+
CouchPotato::Config.database_name = "http://example.com/database"
|
37
|
+
CouchPotato.full_url_to_database.should == 'http://example.com/database'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should use localhost when no protocol was specified" do
|
41
|
+
CouchPotato::Config.database_name = "database"
|
42
|
+
CouchPotato.full_url_to_database.should == 'http://127.0.0.1:5984/database'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe CouchPotato::Database, 'load' do
|
47
|
+
it "should raise an exception if nil given" do
|
48
|
+
db = CouchPotato::Database.new(stub('couchrest db', :info => nil))
|
49
|
+
lambda {
|
50
|
+
db.load nil
|
51
|
+
}.should raise_error("Can't load a document without an id (got nil)")
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should set itself on the model" do
|
55
|
+
user = mock 'user'
|
56
|
+
DbTestUser.stub!(:new).and_return(user)
|
57
|
+
db = CouchPotato::Database.new(stub('couchrest db', :info => nil, :get => DbTestUser.json_create({JSON.create_id => 'DbTestUser'})))
|
58
|
+
user.should_receive(:database=).with(db)
|
59
|
+
db.load '1'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should load namespaced models" do
|
63
|
+
db = CouchPotato::Database.new(stub('couchrest db', :info => nil, :get => Parent::Child.json_create({JSON.create_id => 'Parent::Child'})))
|
64
|
+
db.load('1').class.should == Parent::Child
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
describe CouchPotato::Database, 'save_document' do
|
70
|
+
before(:each) do
|
71
|
+
@db = CouchPotato::Database.new(stub('couchrest db').as_null_object)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should set itself on the model for a new object before doing anything else" do
|
75
|
+
@db.stub(:valid_document?).and_return false
|
76
|
+
user = stub('user', :new? => true).as_null_object
|
77
|
+
user.should_receive(:database=).with(@db)
|
78
|
+
@db.save_document user
|
79
|
+
end
|
80
|
+
|
81
|
+
class Category
|
82
|
+
include CouchPotato::Persistence
|
83
|
+
property :name
|
84
|
+
validates_presence_of :name
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should return false when creating a new document and the validations failed" do
|
88
|
+
CouchPotato.database.save_document(Category.new).should == false
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should return false when saving an existing document and the validations failed" do
|
92
|
+
category = Category.new(:name => "pizza")
|
93
|
+
CouchPotato.database.save_document(category).should == true
|
94
|
+
category.name = nil
|
95
|
+
CouchPotato.database.save_document(category).should == false
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "when creating with validate options" do
|
99
|
+
it "should not run the validations when saved with false" do
|
100
|
+
category = Category.new
|
101
|
+
@db.save_document(category, false)
|
102
|
+
category.new?.should == false
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should run the validations when saved with true" do
|
106
|
+
category = Category.new
|
107
|
+
@db.save_document(category, true)
|
108
|
+
category.new?.should == true
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should run the validations when saved with default" do
|
112
|
+
category = Category.new
|
113
|
+
@db.save_document(category)
|
114
|
+
category.new?.should == true
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "when updating with validate options" do
|
119
|
+
it "should not run the validations when saved with false" do
|
120
|
+
category = Category.new(:name => 'food')
|
121
|
+
@db.save_document(category)
|
122
|
+
category.new?.should == false
|
123
|
+
category.name = nil
|
124
|
+
@db.save_document(category, false)
|
125
|
+
category.dirty?.should == false
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should run the validations when saved with true" do
|
129
|
+
category = Category.new(:name => "food")
|
130
|
+
@db.save_document(category)
|
131
|
+
category.new?.should == false
|
132
|
+
category.name = nil
|
133
|
+
@db.save_document(category, true)
|
134
|
+
category.dirty?.should == true
|
135
|
+
category.valid?.should == false
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should run the validations when saved with default" do
|
139
|
+
category = Category.new(:name => "food")
|
140
|
+
@db.save_document(category)
|
141
|
+
category.new?.should == false
|
142
|
+
category.name = nil
|
143
|
+
@db.save_document(category)
|
144
|
+
category.dirty?.should == true
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "when saving documents with errors set in callbacks" do
|
149
|
+
class Vulcan
|
150
|
+
include CouchPotato::Persistence
|
151
|
+
before_validation_on_create :set_errors
|
152
|
+
before_validation_on_update :set_errors
|
153
|
+
|
154
|
+
property :name
|
155
|
+
validates_presence_of :name
|
156
|
+
|
157
|
+
def set_errors
|
158
|
+
errors.add(:validation, "failed")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should keep errors added in before_validation_on_* callbacks when creating a new object" do
|
163
|
+
spock = Vulcan.new(:name => 'spock')
|
164
|
+
@db.save_document(spock)
|
165
|
+
spock.errors.on(:validation).should == 'failed'
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should keep errors added in before_validation_on_* callbacks when creating a new object" do
|
169
|
+
spock = Vulcan.new(:name => 'spock')
|
170
|
+
@db.save_document(spock, false)
|
171
|
+
spock.new?.should == false
|
172
|
+
spock.name = "spock's father"
|
173
|
+
@db.save_document(spock)
|
174
|
+
spock.errors.on(:validation).should == 'failed'
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should keep errors generated from normal validations together with errors set in normal validations" do
|
178
|
+
spock = Vulcan.new
|
179
|
+
@db.save_document(spock)
|
180
|
+
spock.errors.on(:validation).should == 'failed'
|
181
|
+
spock.errors.on(:name).should =~ /can't be (empty|blank)/
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should clear errors on subsequent, valid saves when creating" do
|
185
|
+
spock = Vulcan.new
|
186
|
+
@db.save_document(spock)
|
187
|
+
|
188
|
+
spock.name = 'Spock'
|
189
|
+
@db.save_document(spock)
|
190
|
+
spock.errors.on(:name).should == nil
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should clear errors on subsequent, valid saves when updating" do
|
194
|
+
spock = Vulcan.new(:name => 'spock')
|
195
|
+
@db.save_document(spock, false)
|
196
|
+
|
197
|
+
spock.name = nil
|
198
|
+
@db.save_document(spock)
|
199
|
+
spock.errors.on(:name).should =~ /can't be (empty|blank)/
|
200
|
+
|
201
|
+
spock.name = 'Spock'
|
202
|
+
@db.save_document(spock)
|
203
|
+
spock.errors.on(:name).should == nil
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
describe CouchPotato::Database, 'view' do
|
210
|
+
before(:each) do
|
211
|
+
@couchrest_db = stub('couchrest db').as_null_object
|
212
|
+
@db = CouchPotato::Database.new(@couchrest_db)
|
213
|
+
@result = stub('result')
|
214
|
+
@spec = stub('view spec', :process_results => [@result]).as_null_object
|
215
|
+
CouchPotato::View::ViewQuery.stub(:new => stub('view query', :query_view! => {'rows' => [@result]}))
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should initialze a view query with map/reduce/list funtions" do
|
219
|
+
@spec.stub(:design_document => 'design_doc', :view_name => 'my_view',
|
220
|
+
:map_function => '<map_code>', :reduce_function => '<reduce_code>',
|
221
|
+
:list_name => 'my_list', :list_function => '<list_code>')
|
222
|
+
CouchPotato::View::ViewQuery.should_receive(:new).with(
|
223
|
+
@couchrest_db,
|
224
|
+
'design_doc',
|
225
|
+
{'my_view' => {
|
226
|
+
:map => '<map_code>',
|
227
|
+
:reduce => '<reduce_code>'
|
228
|
+
}},
|
229
|
+
{'my_list' => '<list_code>'})
|
230
|
+
@db.view(@spec)
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should initialze a view query with only map/reduce functions" do
|
234
|
+
@spec.stub(:design_document => 'design_doc', :view_name => 'my_view',
|
235
|
+
:map_function => '<map_code>', :reduce_function => '<reduce_code>',
|
236
|
+
:list_name => nil, :list_function => nil)
|
237
|
+
CouchPotato::View::ViewQuery.should_receive(:new).with(
|
238
|
+
@couchrest_db,
|
239
|
+
'design_doc',
|
240
|
+
{'my_view' => {
|
241
|
+
:map => '<map_code>',
|
242
|
+
:reduce => '<reduce_code>'
|
243
|
+
}}, nil)
|
244
|
+
@db.view(@spec)
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should set itself on returned results that have an accessor" do
|
248
|
+
@result.stub(:respond_to?).with(:database=).and_return(true)
|
249
|
+
@result.should_receive(:database=).with(@db)
|
250
|
+
@db.view(@spec)
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should not set itself on returned results that don't have an accessor" do
|
254
|
+
@result.stub(:respond_to?).with(:database=).and_return(false)
|
255
|
+
@result.should_not_receive(:database=).with(@db)
|
256
|
+
@db.view(@spec)
|
257
|
+
end
|
258
|
+
|
259
|
+
it "should not try to set itself on result sets that are not collections" do
|
260
|
+
lambda {
|
261
|
+
@spec.stub(:process_results => 1)
|
262
|
+
}.should_not raise_error
|
263
|
+
|
264
|
+
@db.view(@spec)
|
265
|
+
end
|
266
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Date, 'to_json' do
|
4
|
+
it "should format the date in a way that i can use it for sorting in couchdb" do
|
5
|
+
date = Date.parse('2009-01-01')
|
6
|
+
date.to_json.should == "\"2009/01/01\""
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe Date, 'to_s(:json)' do
|
11
|
+
it "should format it in the same way as to_json does so i can use this to do queries over date attributes" do
|
12
|
+
date = Date.parse('2009-01-01')
|
13
|
+
date.to_s(:json).should == "2009/01/01"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Date, 'to_s' do
|
18
|
+
it "should leave the original to_s untouched" do
|
19
|
+
date = Date.parse('2009-01-01')
|
20
|
+
date.to_s.should == "2009-01-01"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Plate
|
4
|
+
include CouchPotato::Persistence
|
5
|
+
|
6
|
+
property :food
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'dirty attribute tracking' do
|
10
|
+
before(:each) do
|
11
|
+
@couchrest_db = stub('database', :save_doc => {'id' => '1', 'rev' => '2'}, :info => nil)
|
12
|
+
@db = CouchPotato::Database.new(@couchrest_db)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "save" do
|
16
|
+
it "should not save when nothing dirty" do
|
17
|
+
plate = Plate.new :food => 'sushi'
|
18
|
+
@db.save_document!(plate)
|
19
|
+
@couchrest_db.should_not_receive(:save_doc)
|
20
|
+
@db.save_document(plate)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return true when not dirty" do
|
24
|
+
plate = Plate.new :food => 'sushi'
|
25
|
+
@db.save_document!(plate)
|
26
|
+
@db.save_document(plate).should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should save when there are dirty attributes" do
|
30
|
+
plate = Plate.new :food => 'sushi'
|
31
|
+
@db.save_document!(plate)
|
32
|
+
plate.food = 'burger'
|
33
|
+
@couchrest_db.should_receive(:save_doc)
|
34
|
+
@db.save_document(plate)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should correctly track dirty hashes (deep clone)" do
|
38
|
+
plate = Plate.new :food => {:veggies => ['carrots', 'peas']}
|
39
|
+
@db.save_document(plate)
|
40
|
+
plate.food[:veggies] << 'beans'
|
41
|
+
@couchrest_db.should_receive(:save_doc)
|
42
|
+
@db.save_document(plate)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should correctly track dirty hashes (deep clone) after a save" do
|
46
|
+
plate = Plate.new :food => {:veggies => ['carrots', 'peas']}
|
47
|
+
@db.save_document(plate)
|
48
|
+
plate.food[:veggies] << 'beans'
|
49
|
+
@db.save_document(plate)
|
50
|
+
plate.food[:veggies] << 'cauliflower'
|
51
|
+
@couchrest_db.should_receive(:save_doc)
|
52
|
+
@db.save_document(plate)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "newly created object" do
|
57
|
+
|
58
|
+
before(:each) do
|
59
|
+
@plate = Plate.new :food => 'sushi'
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "access old values" do
|
63
|
+
it "should return the old value" do
|
64
|
+
@plate.food = 'burger'
|
65
|
+
@plate.food_was.should == 'sushi'
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "with type BigDecimal" do
|
69
|
+
before(:each) do
|
70
|
+
class ::Plate
|
71
|
+
property :price
|
72
|
+
end
|
73
|
+
end
|
74
|
+
it "should not dup BigDecimal" do
|
75
|
+
|
76
|
+
lambda {
|
77
|
+
Plate.new :price => BigDecimal.new("5.23")
|
78
|
+
}.should_not raise_error(TypeError)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should return the old value" do
|
82
|
+
plate = Plate.new :price => BigDecimal.new("5.23")
|
83
|
+
plate.price = BigDecimal.new("2.23")
|
84
|
+
plate.price_was.should == 5.23
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "check for dirty" do
|
91
|
+
it "should return true if attribute changed" do
|
92
|
+
@plate.food = 'burger'
|
93
|
+
@plate.should be_food_changed
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should return false if attribute not changed" do
|
97
|
+
@plate.should_not be_food_changed
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should return false if attribute forced not changed" do
|
101
|
+
@plate.food = 'burger'
|
102
|
+
@plate.food_not_changed
|
103
|
+
@plate.should_not be_food_changed
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should return true if forced dirty" do
|
107
|
+
@plate.is_dirty
|
108
|
+
@plate.should be_dirty
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "object loaded from database" do
|
114
|
+
before(:each) do
|
115
|
+
couchrest_db = stub('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', JSON.create_id => 'Plate'}), :info => nil)
|
116
|
+
@plate = CouchPotato::Database.new(couchrest_db).load_document '1'
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "access old values" do
|
120
|
+
it "should return the old value" do
|
121
|
+
@plate.food = 'burger'
|
122
|
+
@plate.food_was.should == 'sushi'
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe "check for dirty" do
|
127
|
+
it "should return true if attribute changed" do
|
128
|
+
@plate.food = 'burger'
|
129
|
+
@plate.should be_food_changed
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should return true if array attribute changed" do
|
133
|
+
couchrest_db = stub('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => ['sushi'], JSON.create_id => 'Plate'}), :info => nil)
|
134
|
+
plate = CouchPotato::Database.new(couchrest_db).load_document '1'
|
135
|
+
plate.food << 'burger'
|
136
|
+
plate.should be_food_changed
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should return false if attribute not changed" do
|
140
|
+
@plate.should_not be_food_changed
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
describe "after save" do
|
147
|
+
it "should reset all attributes to not dirty" do
|
148
|
+
couchrest_db = stub('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', JSON.create_id => 'Plate'}), :info => nil, :save_doc => {})
|
149
|
+
db = CouchPotato::Database.new(couchrest_db)
|
150
|
+
@plate = db.load_document '1'
|
151
|
+
@plate.food = 'burger'
|
152
|
+
db.save! @plate
|
153
|
+
@plate.should_not be_food_changed
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should reset a forced dirty state" do
|
157
|
+
couchrest_db = stub('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', JSON.create_id => 'Plate'}), :info => nil, :save_doc => {'rev' => '3'})
|
158
|
+
db = CouchPotato::Database.new(couchrest_db)
|
159
|
+
@plate = db.load_document '1'
|
160
|
+
@plate.is_dirty
|
161
|
+
db.save! @plate
|
162
|
+
@plate.should_not be_dirty
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Drink
|
4
|
+
include CouchPotato::Persistence
|
5
|
+
|
6
|
+
property :alcohol
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "json module" do
|
10
|
+
it "should inject JSON.create_id into hash representation of a persistence object" do
|
11
|
+
sake = Drink.new(:alcohol => "18%")
|
12
|
+
sake.to_hash[JSON.create_id].should eql("Drink")
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CouchPotato::View::Lists, '.list' do
|
4
|
+
it "should make the list function available via .lists" do
|
5
|
+
clazz = Class.new
|
6
|
+
clazz.send :include, CouchPotato::View::Lists
|
7
|
+
clazz.list 'my_list', '<list_code>'
|
8
|
+
|
9
|
+
clazz.lists('my_list').should == '<list_code>'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should make the list available to subclasses" do
|
13
|
+
clazz = Class.new
|
14
|
+
clazz.send :include, CouchPotato::View::Lists
|
15
|
+
clazz.list 'my_list', '<list_code>'
|
16
|
+
sub_clazz = Class.new clazz
|
17
|
+
|
18
|
+
sub_clazz.lists('my_list').should == '<list_code>'
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CouchPotato::View::ModelViewSpec, 'map_function' do
|
4
|
+
it "should include conditions" do
|
5
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:conditions => 'doc.closed = true'}, {}
|
6
|
+
spec.map_function.should include("if(doc.#{CouchPotato.type_field} && doc.#{CouchPotato.type_field} == 'Object' && (doc.closed = true))")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should not include conditions when they are nil" do
|
10
|
+
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {}, {}
|
11
|
+
spec.map_function.should include("if(doc.#{CouchPotato.type_field} && doc.#{CouchPotato.type_field} == 'Object')")
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'couch_potato/rspec'
|
3
|
+
|
4
|
+
class Contract
|
5
|
+
include CouchPotato::Persistence
|
6
|
+
|
7
|
+
property :date
|
8
|
+
property :terms
|
9
|
+
|
10
|
+
view :by_date, :type => :properties, :key => :_id, :properties => [:date]
|
11
|
+
end
|
12
|
+
|
13
|
+
describe CouchPotato::View::PropertiesViewSpec do
|
14
|
+
it "should map the given properties" do
|
15
|
+
Contract.by_date.should map(
|
16
|
+
Contract.new(:date => '2010-01-01', :_id => '1')
|
17
|
+
).to(['1', {"date" => "2010-01-01"}])
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should reduce to the number of documents" do
|
21
|
+
Contract.by_date.should reduce(
|
22
|
+
['1', {"date" => "2010-01-01"}], ['2', {"date" => "2010-01-02"}]
|
23
|
+
).to(2)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should rereduce the number of documents" do
|
27
|
+
Contract.by_date.should rereduce(
|
28
|
+
nil, [12, 13]
|
29
|
+
).to(25)
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'couch_potato/rspec'
|
3
|
+
|
4
|
+
describe CouchPotato::RSpec::MapToMatcher do
|
5
|
+
|
6
|
+
describe "basic map function" do
|
7
|
+
before(:each) do
|
8
|
+
@view_spec = stub(:map_function => "function(doc) {emit(doc.name, doc.tags.length);}")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should pass if the given function emits the expected javascript" do
|
12
|
+
@view_spec.should map({:name => 'horst', :tags => ['person', 'male']}).to(['horst', 2])
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should not pass if the given function emits different javascript" do
|
16
|
+
@view_spec.should_not map({:name => 'horst', :tags => ['person', 'male']}).to(['horst', 3])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "functions emitting multiple times" do
|
21
|
+
before(:each) do
|
22
|
+
@view_spec = stub(:map_function => "function(doc) {emit(doc.name, doc.tags.length); emit(doc.tags[0], doc.tags[1])};")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should pass if the given function emits the expected javascript" do
|
26
|
+
@view_spec.should map({:name => 'horst', :tags => ['person', 'male']}).to(['horst', 2], ['person', 'male'])
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return false if the given function emits different javascript" do
|
30
|
+
@view_spec.should_not map({:name => 'horst', :tags => ['person', 'male']}).to(['horst', 2], ['male', 'person'])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "failing specs" do
|
35
|
+
before(:each) do
|
36
|
+
@view_spec = stub(:map_function => "function(doc) {emit(doc.name, null)}")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should have a nice error message for failing should" do
|
40
|
+
lambda {
|
41
|
+
@view_spec.should map({:name => 'bill'}).to(['linus', nil])
|
42
|
+
}.should raise_error('Expected to map to [["linus", nil]] but got [["bill", nil]].')
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should have a nice error message for failing should not" do
|
46
|
+
lambda {
|
47
|
+
@view_spec.should_not map({:name => 'bill'}).to(['bill', nil])
|
48
|
+
}.should raise_error('Expected not to map to [["bill", nil]] but did.')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe CouchPotato::RSpec::ReduceToMatcher do
|
54
|
+
before(:each) do
|
55
|
+
@view_spec = stub(:reduce_function => "function(docs, keys, rereduce) {
|
56
|
+
if(rereduce) {
|
57
|
+
return(sum(keys) * 2);
|
58
|
+
} else {
|
59
|
+
return(sum(keys));
|
60
|
+
};
|
61
|
+
}")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should pass if the given function return the expected javascript" do
|
65
|
+
@view_spec.should reduce([], [1, 2, 3]).to(6)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should not pass if the given function returns different javascript" do
|
69
|
+
@view_spec.should_not reduce([], [1, 2, 3]).to(7)
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "rereduce" do
|
73
|
+
it "should pass if the given function return the expected javascript" do
|
74
|
+
@view_spec.should rereduce([], [1, 2, 3]).to(12)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should not pass if the given function returns different javascript" do
|
78
|
+
@view_spec.should_not rereduce([], [1, 2, 3]).to(13)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'failing specs' do
|
83
|
+
|
84
|
+
it "should have a nice error message for failing should" do
|
85
|
+
lambda {
|
86
|
+
@view_spec.should reduce([], [1, 2, 3]).to(7)
|
87
|
+
}.should raise_error('Expected to reduce to 7 but got 6.')
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should have a nice error message for failing should not" do
|
91
|
+
lambda {
|
92
|
+
@view_spec.should_not reduce([], [1, 2, 3]).to(6)
|
93
|
+
}.should raise_error('Expected not to reduce to 6 but did.')
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe CouchPotato::RSpec::ListAsMatcher do
|
99
|
+
before(:each) do
|
100
|
+
@view_spec = stub(:list_function => "function() {var row = getRow(); send(JSON.stringify([{text: row.text + ' world'}]));}")
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should pass if the function return the expected json" do
|
104
|
+
@view_spec.should list({'rows' => [{:text => 'hello'}]}).as([{'text' => 'hello world'}])
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should not pass if the function does not return the expected json" do
|
108
|
+
@view_spec.should_not list({'rows' => [{:text => 'hello'}]}).as([{'text' => 'hello there'}])
|
109
|
+
end
|
110
|
+
|
111
|
+
describe "failing specs" do
|
112
|
+
it "should have a nice error message for failing should" do
|
113
|
+
lambda {
|
114
|
+
@view_spec.should list({'rows' => [{:text => 'hello'}]}).as([{'text' => 'hello there'}])
|
115
|
+
}.should raise_error('Expected to list as [{"text"=>"hello there"}] but got [{"text"=>"hello world"}].')
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should have a nice error message for failing should not" do
|
119
|
+
lambda {
|
120
|
+
@view_spec.should_not list({'rows' => [{:text => 'hello'}]}).as([{'text' => 'hello world'}])
|
121
|
+
}.should raise_error('Expected to not list as [{"text"=>"hello world"}] but did.')
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'couch_potato/rspec'
|
3
|
+
|
4
|
+
class WithStubbedView
|
5
|
+
include CouchPotato::Persistence
|
6
|
+
|
7
|
+
view :stubbed_view, :key => :x
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "stubbing the db" do
|
11
|
+
it "should replace CouchPotato.database with a stub" do
|
12
|
+
stub_db
|
13
|
+
CouchPotato.database.should be_a(Spec::Mocks::Mock)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return the stub" do
|
17
|
+
db = stub_db
|
18
|
+
CouchPotato.database.should == db
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "stubbing a view" do
|
23
|
+
before(:each) do
|
24
|
+
@db = stub_db
|
25
|
+
@db.stub_view(WithStubbedView, :stubbed_view).with('123').and_return([:result])
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should stub the view to return a stub" do
|
29
|
+
WithStubbedView.stubbed_view('123').should be_a(Spec::Mocks::Mock)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should stub the database to return fake results when called with the stub" do
|
33
|
+
@db.view(WithStubbedView.stubbed_view('123')).should == [:result]
|
34
|
+
end
|
35
|
+
end
|