rocking_chair 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,447 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ class DatabaseTest < Test::Unit::TestCase
4
+ context "The database engine" do
5
+ setup do
6
+ @db = RockingChair::Database.new
7
+ end
8
+
9
+ context "when asking for a UUID" do
10
+ should "return a uuid" do
11
+ assert_not_nil RockingChair::Database.uuid
12
+ end
13
+
14
+ should "always return a fresh one" do
15
+ first_id = RockingChair::Database.uuid
16
+ assert_not_equal first_id, RockingChair::Database.uuid
17
+ end
18
+
19
+ should "return a list of UUIDs" do
20
+ assert_equal 3, RockingChair::Database.uuids(3).uniq.size
21
+ end
22
+ end
23
+
24
+ context "when storing" do
25
+ should "store an element by id" do
26
+ @db.stubs(:rev).returns('rev')
27
+ @db['abc'] = {:a => :b}.to_json
28
+ assert_equal({'a' => 'b', '_rev' => 'rev', '_id' => 'abc'}, JSON.parse(@db['abc']))
29
+ end
30
+
31
+ should "assing an ID is none given" do
32
+ @db.stubs(:rev).returns('rev')
33
+ RockingChair::Database.expects(:uuid).returns('uuid')
34
+ assert_equal( {"rev" => "rev", "id" => "uuid", "ok" => true}, JSON.parse(@db.store(nil, {'a' => 'b'}.to_json)))
35
+ end
36
+
37
+ should "make sure the content is valid JSON" do
38
+ assert_error_code(500) do
39
+ @db['abc'] = 'string'
40
+ end
41
+ end
42
+
43
+ should "return the state tuple" do
44
+ @db.expects(:rev).returns('946B7D1C')
45
+ assert_equal({"ok" => true, "id" => "some_doc_id", "rev" => "946B7D1C"}.to_json, @db.store('some_doc_id', {:a => :b}.to_json) )
46
+ end
47
+
48
+ should "set the id if none given" do
49
+ _id = JSON.parse(@db.store(nil, {:a => :b}.to_json))['_id']
50
+ assert_not_nil JSON.parse(@db[_id])['_id']
51
+ end
52
+
53
+ should "populate the id" do
54
+ @db['abc'] = {:a => :b}.to_json
55
+ assert_equal 'abc', JSON.parse(@db['abc'])['_id']
56
+ end
57
+
58
+ should "populate the revision" do
59
+ @db['abc'] = {:a => :b}.to_json
60
+ assert_not_nil JSON.parse(@db['abc'])['_rev']
61
+ end
62
+
63
+ should "get the document count" do
64
+ assert_equal 0, @db.document_count
65
+ @db['a'] = {:a => :b}.to_json
66
+ assert_equal 1, @db.document_count
67
+ @db['b'] = {:a => :b}.to_json
68
+ assert_equal 2, @db.document_count
69
+ @db['c'] = {:a => :b}.to_json
70
+ assert_equal 3, @db.document_count
71
+ end
72
+
73
+ context "when updating" do
74
+ should "update the content" do
75
+ state = JSON.parse( @db.store('abc', {:a => :b}.to_json ))
76
+ @db['abc'] = {:a => :c, :_rev => state['rev']}.to_json
77
+ assert_equal 'c', JSON.parse(@db['abc'])['a']
78
+ end
79
+
80
+ should "raise an error if the revs aren't matching" do
81
+ @db.store('abc', {:a => :b}.to_json )
82
+ assert_error_code(409) do
83
+ @db['abc'] = {:a => :c, :_rev => 'REV'}.to_json
84
+ end
85
+ assert_equal 'b', JSON.parse(@db['abc'])['a']
86
+ end
87
+ end
88
+ end
89
+
90
+ context "when deleting" do
91
+ setup do
92
+ @state = JSON.parse(@db.store('abc',{:a => :b}.to_json))
93
+ end
94
+
95
+ should "delete only if the revision matches" do
96
+ assert_error_code 409 do
97
+ @db.delete('abc', 'revrev')
98
+ end
99
+ assert_nothing_raised do
100
+ @db.delete('abc', @state['rev'])
101
+ end
102
+ assert_error_code 404 do
103
+ @db['abc']
104
+ end
105
+ end
106
+ end
107
+
108
+ context "when copying" do
109
+ setup do
110
+ @state = JSON.parse(@db.store('abc',{:a => :b}.to_json))
111
+ end
112
+
113
+ should "copy" do
114
+ @db.expects(:rev).returns('355068078')
115
+ @state = JSON.parse(@db.copy('abc', 'def'))
116
+ assert_equal({"ok" => true, "id" => "def", "rev" => "355068078"}, @state)
117
+ assert_equal({'a' => 'b', '_id' => 'def', '_rev' => "355068078"}, JSON.parse(@db['def']))
118
+ end
119
+
120
+ should "raise 404 if the original if not found" do
121
+ assert_error_code 404 do
122
+ @db.copy('abceeee', 'def')
123
+ end
124
+ end
125
+
126
+ should "raise 409 if no rev given but destination exists" do
127
+ @db.store('destination',{:c => :e}.to_json)
128
+ assert_error_code 409 do
129
+ @db.copy('abc', 'destination')
130
+ end
131
+ end
132
+
133
+ should "raise 409 if the rev does not match" do
134
+ @state = JSON.parse(@db.store('def',{'1' => '2'}.to_json))
135
+
136
+ @db.expects(:rev).returns('355068078')
137
+ assert_error_code 409 do
138
+ @db.copy('abc', 'def', 'revrev')
139
+ end
140
+ assert_nothing_raised do
141
+ @db.copy('abc', 'def', @state['rev'])
142
+ end
143
+ assert_equal({'a' => 'b', '_id' => 'def', '_rev' => "355068078"}, JSON.parse(@db['def']))
144
+ end
145
+ end
146
+
147
+ context "when loading documents by id" do
148
+ should "return the matching document" do
149
+ @db.stubs(:rev).returns('rev')
150
+ @db['a'] = {:a => :b}.to_json
151
+ @db['b'] = {1 => 2}.to_json
152
+ assert_equal({'a' => 'b', '_rev' => 'rev', '_id' => 'a'}, JSON.parse(@db['a']))
153
+ end
154
+
155
+ should "return a matching document by revision" do
156
+ @db.stubs(:rev).returns('rev')
157
+ @db['a'] = {:a => :b}.to_json
158
+ assert_equal({'a' => 'b', '_rev' => 'rev', '_id' => 'a'}, JSON.parse(@db.load('a', 'rev' => 'rev')))
159
+ end
160
+
161
+ should "raise a 404 if there is no matching document" do
162
+ assert_error_code(404) do
163
+ @db['no-such-key']
164
+ end
165
+ end
166
+
167
+ should "raise a 404 if the revision does not match" do
168
+ @db.stubs(:rev).returns('rev')
169
+ @db['a'] = {:a => :b}.to_json
170
+ assert_error_code(404) do
171
+ @db.load('a', 'rev' => 'no-such-rev')
172
+ end
173
+ end
174
+
175
+ should "load the revision history" do
176
+ @db.stubs(:rev).returns('rev')
177
+ @db['a'] = {:a => :b}.to_json
178
+ assert_equal({'a' => 'b', '_rev' => 'rev', '_id' => 'a', '_revisions' => {'start' => 1, 'ids' => ['rev']}}, JSON.parse(@db.load('a', 'revs' => 'true')))
179
+ end
180
+ end
181
+
182
+ context "when loading all documents" do
183
+ should "return all docs" do
184
+ @db.stubs(:rev).returns('rev')
185
+ 5.times do |i|
186
+ @db["item-#{i}"] = {"data" => "item-#{i}"}.to_json
187
+ end
188
+ assert_equal({
189
+ "total_rows" => 5, "offset" => 0, "rows" => [
190
+ {"id" => "item-0", "key" => "item-0", "value" => {"rev" => "rev"}},
191
+ {"id" => "item-1", "key" => "item-1", "value" => {"rev" => "rev"}},
192
+ {"id" => "item-2", "key" => "item-2", "value" => {"rev" => "rev"}},
193
+ {"id" => "item-3", "key" => "item-3", "value" => {"rev" => "rev"}},
194
+ {"id" => "item-4", "key" => "item-4", "value" => {"rev" => "rev"}}
195
+ ]
196
+ }.to_json, @db.all_documents)
197
+ end
198
+
199
+ should "sort all docs by ID ascending" do
200
+ @db.stubs(:rev).returns('rev')
201
+ @db["C"] = {"data" => "Z"}.to_json
202
+ @db["A"] = {"data" => "Z"}.to_json
203
+ @db["B"] = {"data" => "Z"}.to_json
204
+
205
+ assert_equal({
206
+ "total_rows" => 3, "offset" => 0, "rows" => [
207
+ {"id" => "A", "key" => "A", "value" => {"rev" => "rev"}},
208
+ {"id" => "B", "key" => "B", "value" => {"rev" => "rev"}},
209
+ {"id" => "C", "key" => "C", "value" => {"rev" => "rev"}}
210
+ ]
211
+ }.to_json, @db.all_documents)
212
+ end
213
+
214
+ should "sort all docs by ID descending" do
215
+ @db.stubs(:rev).returns('rev')
216
+ @db["C"] = {"data" => "Z"}.to_json
217
+ @db["A"] = {"data" => "Z"}.to_json
218
+ @db["B"] = {"data" => "Z"}.to_json
219
+
220
+ assert_equal({
221
+ "total_rows" => 3, "offset" => 0, "rows" => [
222
+ {"id" => "C", "key" => "C", "value" => {"rev" => "rev"}},
223
+ {"id" => "B", "key" => "B", "value" => {"rev" => "rev"}},
224
+ {"id" => "A", "key" => "A", "value" => {"rev" => "rev"}}
225
+ ]
226
+ }.to_json, @db.all_documents('descending' => true))
227
+ end
228
+
229
+ should "start by the given key" do
230
+ @db.stubs(:rev).returns('rev')
231
+ @db["C"] = {"data" => "Z"}.to_json
232
+ @db["A"] = {"data" => "Z"}.to_json
233
+ @db["B"] = {"data" => "Z"}.to_json
234
+
235
+ assert_equal({
236
+ "total_rows" => 3, "offset" => 1, "rows" => [
237
+ {"id" => "B", "key" => "B", "value" => {"rev" => "rev"}},
238
+ {"id" => "C", "key" => "C", "value" => {"rev" => "rev"}}
239
+ ]
240
+ }.to_json, @db.all_documents('startkey' => 'B'))
241
+ end
242
+
243
+ should "start by the given key and ignore quotes" do
244
+ @db.stubs(:rev).returns('rev')
245
+ @db["C"] = {"data" => "Z"}.to_json
246
+ @db["A"] = {"data" => "Z"}.to_json
247
+ @db["B"] = {"data" => "Z"}.to_json
248
+
249
+ assert_equal({
250
+ "total_rows" => 3, "offset" => 1, "rows" => [
251
+ {"id" => "B", "key" => "B", "value" => {"rev" => "rev"}},
252
+ {"id" => "C", "key" => "C", "value" => {"rev" => "rev"}}
253
+ ]
254
+ }.to_json, @db.all_documents('startkey' => '"B"'))
255
+ end
256
+
257
+ should "combine start and limit" do
258
+ @db.stubs(:rev).returns('rev')
259
+ @db["C"] = {"data" => "Z"}.to_json
260
+ @db["A"] = {"data" => "Z"}.to_json
261
+ @db["B"] = {"data" => "Z"}.to_json
262
+ @db["D"] = {"data" => "Z"}.to_json
263
+
264
+ assert_equal({
265
+ "total_rows" => 4, "offset" => 1, "rows" => [
266
+ {"id" => "B", "key" => "B", "value" => {"rev" => "rev"}}
267
+ ]
268
+ }.to_json, @db.all_documents('startkey' => 'B', 'limit' => '1'))
269
+ end
270
+
271
+ should "combine start and descending" do
272
+ @db.stubs(:rev).returns('rev')
273
+ @db["C"] = {"data" => "Z"}.to_json
274
+ @db["A"] = {"data" => "Z"}.to_json
275
+ @db["B"] = {"data" => "Z"}.to_json
276
+ @db["D"] = {"data" => "Z"}.to_json
277
+
278
+ assert_equal({
279
+ "total_rows" => 4, "offset" => 2, "rows" => [
280
+ {"id" => "B", "key" => "B", "value" => {"rev" => "rev"}},
281
+ {"id" => "A", "key" => "A", "value" => {"rev" => "rev"}}
282
+ ]
283
+ }.to_json, @db.all_documents('startkey' => 'B', 'descending' => 'true'))
284
+ end
285
+
286
+ should "combine start, limit, and descending" do
287
+ @db.stubs(:rev).returns('rev')
288
+ @db["C"] = {"data" => "Z"}.to_json
289
+ @db["A"] = {"data" => "Z"}.to_json
290
+ @db["B"] = {"data" => "Z"}.to_json
291
+ @db["D"] = {"data" => "Z"}.to_json
292
+
293
+ assert_equal({
294
+ "total_rows" => 4, "offset" => 2, "rows" => [
295
+ {"id" => "B", "key" => "B", "value" => {"rev" => "rev"}}
296
+ ]
297
+ }.to_json, @db.all_documents('startkey' => 'B', 'descending' => 'true', 'limit' => '1'))
298
+ end
299
+
300
+ should "end by the given key" do
301
+ @db.stubs(:rev).returns('rev')
302
+ @db["C"] = {"data" => "Z"}.to_json
303
+ @db["A"] = {"data" => "Z"}.to_json
304
+ @db["B"] = {"data" => "Z"}.to_json
305
+
306
+ assert_equal({
307
+ "total_rows" => 3, "offset" => 0, "rows" => [
308
+ {"id" => "A", "key" => "A", "value" => {"rev" => "rev"}},
309
+ {"id" => "B", "key" => "B", "value" => {"rev" => "rev"}}
310
+ ]
311
+ }.to_json, @db.all_documents('endkey' => 'B'))
312
+ end
313
+
314
+ should "combine start and end key" do
315
+ @db.stubs(:rev).returns('rev')
316
+ @db["C"] = {"data" => "Z"}.to_json
317
+ @db["A"] = {"data" => "Z"}.to_json
318
+ @db["B"] = {"data" => "Z"}.to_json
319
+ @db["D"] = {"data" => "Z"}.to_json
320
+
321
+ assert_equal({
322
+ "total_rows" => 4, "offset" => 1, "rows" => [
323
+ {"id" => "B", "key" => "B", "value" => {"rev" => "rev"}},
324
+ {"id" => "C", "key" => "C", "value" => {"rev" => "rev"}}
325
+ ]
326
+ }.to_json, @db.all_documents('startkey' => 'B', 'endkey' => 'C'))
327
+ end
328
+
329
+ should "combine start, end key, and include_docs" do
330
+ @db.stubs(:rev).returns('rev')
331
+ @db["C"] = {"data" => "Z"}.to_json
332
+ @db["A"] = {"data" => "Z"}.to_json
333
+ @db["B"] = {"data" => "Z"}.to_json
334
+ @db["D"] = {"data" => "Z"}.to_json
335
+
336
+ assert_equal({
337
+ "total_rows" => 4, "offset" => 1, "rows" => [
338
+ {"id" => "B", "key" => "B", "value" => {"rev" => "rev", '_rev' => 'rev', 'data' => 'Z', '_id' => 'B'}},
339
+ {"id" => "C", "key" => "C", "value" => {"rev" => "rev", '_rev' => 'rev', 'data' => 'Z', '_id' => 'C'}}
340
+ ]
341
+ }.to_json, @db.all_documents('startkey' => 'B', 'endkey' => 'C', 'include_docs' => 'true'))
342
+ end
343
+
344
+ end
345
+
346
+ context "when handling bulk updates" do
347
+ setup do
348
+ @db.stubs(:rev).returns('the-revision')
349
+ end
350
+
351
+ should "insert all documents" do
352
+ RockingChair::Database.stubs(:uuid).returns('foo-id')
353
+ assert_equal 0, @db.document_count
354
+ docs = {'docs' => [{"_id" => 'a', "value" => 1}, {"_id" => 'b', 'value' => 2}, {'value' => 3}]}.to_json
355
+ assert_equal([
356
+ {'id' => 'a', "rev" => 'the-revision'},
357
+ {'id' => 'b', "rev" => 'the-revision'},
358
+ {'id' => 'foo-id', "rev" => 'the-revision'}
359
+ ].to_json, @db.bulk(docs))
360
+ end
361
+
362
+ should "update documents" do
363
+ @db["A"] = {"data" => "Z"}.to_json
364
+ @db["B"] = {"data" => "Z"}.to_json
365
+
366
+ docs = {'docs' => [{"_id" => 'A', "data" => 1, '_rev' => 'the-revision'}]}.to_json
367
+ @db.bulk(docs)
368
+ assert_equal({
369
+ '_id' => 'A',
370
+ '_rev' => 'the-revision',
371
+ 'data' => 1
372
+ }, JSON.parse(@db['A']))
373
+ end
374
+
375
+ should "handle conflics gracefully" do
376
+ @db["A"] = {"data" => "Z"}.to_json
377
+ @db["B"] = {"data" => "Z"}.to_json
378
+
379
+ docs = {'docs' => [{"_id" => 'A', "data" => 1, '_rev' => 'the-revision'}, {"_id" => 'B', "data" => 1, '_rev' => 'no-such-revision'}]}.to_json
380
+ assert_nothing_raised do
381
+ assert_equal([
382
+ {'id' => 'A', "rev" => 'the-revision'},
383
+ {'id' => 'B', "error" => 'conflict', 'reason' => 'Document update conflict.'}
384
+ ].to_json, @db.bulk(docs))
385
+ end
386
+ end
387
+
388
+ should "delete" do
389
+ @db["A"] = {"data" => "Z"}.to_json
390
+ @db["B"] = {"data" => "Z"}.to_json
391
+
392
+ docs = {'docs' => [{"_id" => 'A', "data" => 1, '_rev' => 'the-revision'}, {"_id" => 'B', "data" => 1, '_rev' => 'the-revision', '_deleted' => true}]}.to_json
393
+ assert_nothing_raised do
394
+ assert_equal([
395
+ {'id' => 'A', "rev" => 'the-revision'},
396
+ {'id' => 'B', "rev" => 'the-revision'}
397
+ ].to_json, @db.bulk(docs))
398
+ end
399
+ end
400
+ end
401
+
402
+ context "when handling design documents" do
403
+ context "the design doc itself" do
404
+ should "return a description of the design document" do
405
+ @db.stubs(:rev).returns('rev')
406
+ @db['_design/user'] = {'language' => 'javascript', 'views' => {}}.to_json
407
+
408
+ assert_equal({'language' => 'javascript', 'views' => {}, '_rev' => 'rev', '_id' => '_design/user'}, JSON.parse(@db['_design/user']))
409
+ end
410
+
411
+ should "not allow to store invalid design documents" do
412
+ assert_error_code 500 do
413
+ @db['_design/user'] = {'language' => 'javascript', 'huhu' => {}}.to_json
414
+ end
415
+ end
416
+
417
+ should "return a description of the design document including the views" do
418
+ @db.stubs(:rev).returns('rev')
419
+ @db['_design/user'] = { 'language' => 'javascript', 'views' => {
420
+ 'viewname' => {
421
+ 'reduce' => nil,
422
+ 'map' => "function(item){emit(item)}"
423
+ }
424
+ }}.to_json
425
+
426
+ assert_equal({ 'language' => 'javascript', 'views' => {
427
+ 'viewname' => {
428
+ 'reduce' => nil,
429
+ 'map' => "function(item){emit(item)}"
430
+ }},
431
+ '_id' => '_design/user',
432
+ '_rev' => 'rev'
433
+ }, JSON.parse(@db['_design/user']))
434
+ end
435
+
436
+ should "raise a 404 if there is no such design document" do
437
+ assert_error_code 404 do
438
+ @db['_design/foo']
439
+ end
440
+ end
441
+ end
442
+
443
+
444
+
445
+ end
446
+ end
447
+ end
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ class ExtendedCouchRestTest < Test::Unit::TestCase
4
+ context "Extended use cases for CouchRest" do
5
+ setup do
6
+ RockingChair::Server.reset
7
+ SERVER.create_db('couchrest-extendeddoc-example')
8
+ end
9
+
10
+ context "CouchRest::ExtendedDocument" do
11
+ should "save and load Posts" do
12
+ p = Post.new(:title => 'The title', :body => 'The body')
13
+ assert p.save
14
+ post = Post.get(p.id)
15
+ assert_equal 'The title', post.title
16
+ assert_equal 'The body', post.body
17
+ end
18
+
19
+ should "save and load Comments" do
20
+ post = Post.new(:title => 'The title', :body => 'The body')
21
+ assert post.save
22
+ c = Comment.new(:body => 'The body of the comment', :post_id => post.id)
23
+ assert c.save
24
+ comment = Comment.get(c.id)
25
+ assert_equal 'The body of the comment', comment.body
26
+ assert_equal post.id, comment.post_id
27
+ end
28
+ end
29
+
30
+ context "Views" do
31
+
32
+ setup do
33
+ @post = Post.new(:title => 'The title', :body => 'The body')
34
+ assert @post.save
35
+ end
36
+
37
+ # should "support simple by-attribute views" do
38
+ # comment = Comment.new(:body => 'The body of the comment', :post_id => @post.id)
39
+ # assert comment.save
40
+ # lonely_comment = comment = Comment.new(:body => 'The body of the comment', :post_id => nil)
41
+ # assert lonely_comment.save
42
+ #
43
+ # assert_equal [comment.id], Comment.by_post_id(:key => @post.id).map(&:id)
44
+ # end
45
+
46
+ end
47
+
48
+ end
49
+ end