rocking_chair 0.0.2

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.
@@ -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