sr-couchy 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/README.textile +77 -0
  2. data/Rakefile +46 -0
  3. data/bin/couchy +80 -0
  4. data/couchy.gemspec +58 -0
  5. data/lib/couchy.rb +21 -0
  6. data/lib/couchy/database.rb +129 -0
  7. data/lib/couchy/server.rb +89 -0
  8. data/spec/couchy_spec.rb +71 -0
  9. data/spec/database_spec.rb +417 -0
  10. data/spec/fixtures/attachments/test.html +11 -0
  11. data/spec/fixtures/views/lib.js +3 -0
  12. data/spec/fixtures/views/test_view/lib.js +3 -0
  13. data/spec/fixtures/views/test_view/only-map.js +4 -0
  14. data/spec/fixtures/views/test_view/test-map.js +3 -0
  15. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  16. data/spec/spec.opts +6 -0
  17. data/spec/spec_helper.rb +5 -0
  18. data/test/couchy_test.rb +13 -0
  19. data/test/database_test.rb +193 -0
  20. data/test/server_test.rb +211 -0
  21. data/test/test_helper.rb +10 -0
  22. data/vendor/addressable/.gitignore +7 -0
  23. data/vendor/addressable/CHANGELOG +51 -0
  24. data/vendor/addressable/LICENSE +20 -0
  25. data/vendor/addressable/README +24 -0
  26. data/vendor/addressable/Rakefile +51 -0
  27. data/vendor/addressable/lib/addressable/idna.rb +4867 -0
  28. data/vendor/addressable/lib/addressable/uri.rb +2212 -0
  29. data/vendor/addressable/lib/addressable/version.rb +35 -0
  30. data/vendor/addressable/spec/addressable/idna_spec.rb +196 -0
  31. data/vendor/addressable/spec/addressable/uri_spec.rb +3827 -0
  32. data/vendor/addressable/spec/data/rfc3986.txt +3419 -0
  33. data/vendor/addressable/tasks/clobber.rake +2 -0
  34. data/vendor/addressable/tasks/gem.rake +62 -0
  35. data/vendor/addressable/tasks/git.rake +40 -0
  36. data/vendor/addressable/tasks/metrics.rake +22 -0
  37. data/vendor/addressable/tasks/rdoc.rake +29 -0
  38. data/vendor/addressable/tasks/rubyforge.rake +89 -0
  39. data/vendor/addressable/tasks/spec.rake +107 -0
  40. data/vendor/addressable/website/index.html +107 -0
  41. metadata +113 -0
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Test</title>
5
+ </head>
6
+ <body>
7
+ <p>
8
+ Test
9
+ </p>
10
+ </body>
11
+ </html>
@@ -0,0 +1,3 @@
1
+ function globalLib() {
2
+ return "fixture";
3
+ };
@@ -0,0 +1,3 @@
1
+ function justThisView() {
2
+ return "fixture";
3
+ };
@@ -0,0 +1,4 @@
1
+ function(doc) {
2
+ //include-lib
3
+ emit(null, null);
4
+ };
@@ -0,0 +1,3 @@
1
+ function(doc) {
2
+ emit(null, null);
3
+ };
@@ -0,0 +1,3 @@
1
+ function(ks,vs,co) {
2
+ return vs.length;
3
+ };
@@ -0,0 +1,6 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
6
+ --reverse
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ CouchHost = "http://localhost:5984/"
5
+ TestDatabase = 'couchy-test'
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ describe 'Couchy#new' do
4
+ it 'creates a new Server with the given server URI' do
5
+ Couchy::Server.expects(:new).with('uri')
6
+ Couchy.new('uri')
7
+ end
8
+
9
+ specify 'uri default to http://localhost:5984/' do
10
+ server = Couchy.new
11
+ server.uri.to_s.should.equal 'http://localhost:5984/'
12
+ end
13
+ end
@@ -0,0 +1,193 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ describe 'Database' do
4
+ before(:each) do
5
+ @server = stub('server', :get => '', :post => '', :put => '', :delete => '')
6
+ @database = Couchy::Database.new(@server, TestDatabase)
7
+ end
8
+
9
+ it 'has an accessor on its name' do
10
+ @database.name.should.equal TestDatabase
11
+ end
12
+
13
+ it 'has an accessor on the server instance' do
14
+ @database.server.should.equal @server
15
+ end
16
+
17
+ specify '#base64 removes new lines to workaround <https://issues.apache.org/jira/browse/COUCHDB-19>' do
18
+ @database.send(:base64, 'foo').should.equal 'Zm9v'
19
+ end
20
+
21
+ describe 'Encoding attachments of a document' do
22
+ setup do
23
+ Couchy::Database.class_eval { public :encode_attachments_of }
24
+ @server.stubs(:base64).returns('')
25
+ @database = Couchy::Database.new(@server, TestDatabase)
26
+ @attachments = { 'foo' => { 'type' => 'text/plain', 'data' => 'some text' },
27
+ 'bar' => { 'type' => 'text/plain', 'data' => 'same here' }}
28
+ @doc = {:foo => 'bar', '_attachments' => @attachments}
29
+ end
30
+
31
+ it 'returns the doc as is if there is no attachment' do
32
+ @database.encode_attachments_of(:foo => 'bar').should.equal(:foo => 'bar')
33
+ end
34
+
35
+ it 'encodes the data of each attachment in base64' do
36
+ @database.expects(:base64).with('some text').returns('')
37
+ @database.expects(:base64).with('same here').returns('')
38
+ @database.encode_attachments_of(@doc)
39
+ end
40
+
41
+ it 'returns the document with the attachments encoded' do
42
+ doc = @database.encode_attachments_of(@doc)
43
+ doc['_attachments']['foo']['data'].should.equal 'c29tZSB0ZXh0'
44
+ doc['_attachments']['bar']['data'].should.equal 'c2FtZSBoZXJl'
45
+ end
46
+ end
47
+
48
+ describe 'Deleting itselfs' do
49
+ it 'DELETE $database_name' do
50
+ @server.expects(:delete).with(TestDatabase)
51
+ @database.delete!
52
+ end
53
+ end
54
+
55
+ describe 'Getting a list of documents' do
56
+ it 'GET $database_name/_all_docs' do
57
+ @server.expects(:get).with(TestDatabase + '/_all_docs', {})
58
+ @database.documents
59
+ end
60
+
61
+ it 'uses given parameters' do
62
+ @server.expects(:get).with(TestDatabase + '/_all_docs', :startkey => 'somedoc', :count => 3)
63
+ @database.documents(:startkey => 'somedoc', :count => 3)
64
+ end
65
+ end
66
+
67
+ describe 'Getting a document' do
68
+ it 'GET $database_name/$document_id' do
69
+ @server.expects(:get).with("#{TestDatabase}/foobar")
70
+ @database.get('foobar')
71
+ end
72
+
73
+ it 'escapes the given document id' do
74
+ CGI.expects(:escape).with('foobar')
75
+ @database.get('foobar')
76
+ end
77
+ end
78
+
79
+ describe 'Saving a document' do
80
+ it 'encodes attachments of the given document' do
81
+ doc = {:foo => 'bar'}
82
+ @database.expects(:encode_attachments_of).with(doc).returns({})
83
+ @database.save(doc)
84
+ end
85
+
86
+ it 'POST the document to $database_name when no document id is specified' do
87
+ doc = {:foo => 'bar'}
88
+ @server.expects(:post).with(TestDatabase, doc)
89
+ @database.save(doc)
90
+ end
91
+
92
+ describe 'When a document id was specified' do
93
+ it 'PUT the document to $database_name/$document_id' do
94
+ doc = {'_id' => 'mydocid', 'foo' => 'bar'}
95
+ @server.expects(:put).with("#{TestDatabase}/#{doc['_id']}", doc)
96
+ @database.save(doc)
97
+ end
98
+
99
+ it 'escapes the given document id' do
100
+ CGI.expects(:escape).with('mydocid')
101
+ @database.save('_id' => 'mydocid')
102
+ end
103
+ end
104
+ end
105
+
106
+ describe 'Bulk saving a bunch of documents' do
107
+ it 'POST the documents to $database_name/_bulk_docs' do
108
+ @server.expects(:post).with("#{TestDatabase}/_bulk_docs", :docs => ['doc1', 'doc2'])
109
+ @database.bulk_save(['doc1', 'doc2'])
110
+ end
111
+ end
112
+
113
+ describe 'Fetching an attachment' do
114
+ it 'GET $database_name/$document_id/$attachment_id' do
115
+ @server.expects(:get).with("#{TestDatabase}/my-doc/foo", anything)
116
+ @database.fetch_attachment('my-doc', 'foo')
117
+ end
118
+
119
+ it 'escapes the document id and the attachement id' do
120
+ CGI.expects(:escape).with('my-doc')
121
+ CGI.expects(:escape).with('foo')
122
+ @database.fetch_attachment('my-doc', 'foo')
123
+ end
124
+ end
125
+
126
+ describe 'Deleting a document' do
127
+ describe 'When given the document id and the revision' do
128
+ it 'DELETE $database_name/$document_id?rev=$revision' do
129
+ @server.expects(:delete).with("#{TestDatabase}/mydocid", :rev => 2800624930)
130
+ @database.delete('mydocid', 2800624930)
131
+ end
132
+
133
+ it 'escapes the document id' do
134
+ CGI.expects(:escape).with('mydocid')
135
+ @database.delete('mydocid', 2800624930)
136
+ end
137
+ end
138
+
139
+ describe 'When given an Hash representing a document' do
140
+ it 'raises ArgumentError if the doc doesnt have an _id' do
141
+ lambda { @database.delete('foo' => 'bar') }.should.raise(ArgumentError)
142
+ end
143
+
144
+ it 'raises ArgumentError if the doc doesnt have a _rev' do
145
+ lambda { @database.delete('_id' => 'foo') }.should.raise(ArgumentError)
146
+ end
147
+
148
+ it 'DELETE $database_name/$document_id?rev=$revision' do
149
+ @server.expects(:delete).with("#{TestDatabase}/mydocid", :rev => 2800624930)
150
+ @database.delete('_id' => 'mydocid', '_rev' => 2800624930)
151
+ end
152
+
153
+ it 'escapes the document id' do
154
+ CGI.expects(:escape).with('mydocid')
155
+ @database.delete('_id' => 'mydocid', '_rev' => 286633)
156
+ end
157
+ end
158
+
159
+ it 'raises ArgumentError if the given argument is neither a document id nor a document' do
160
+ lambda { @database.delete(:fooo) }.should.raise(ArgumentError)
161
+ end
162
+ end
163
+
164
+ describe 'Creating a temporary view' do
165
+ it 'POST $database_name/_temp_view with the given fonction' do
166
+ @server.expects(:post).with(TestDatabase + '/_temp_view', 'js function', anything)
167
+ @database.temp_view('js function')
168
+ end
169
+
170
+ it "sets the request's Content-Type to application/json" do
171
+ @server.expects(:post).with(anything, anything,
172
+ has_entries(:headers => {'Content-Type' => 'application/json'}))
173
+ @database.temp_view('foo')
174
+ end
175
+
176
+ it 'uses the given parameters' do
177
+ @server.expects(:post).with(anything, 'foo', has_entries(:startkey => 'foo'))
178
+ @database.temp_view('foo', :startkey => 'foo')
179
+ end
180
+ end
181
+
182
+ describe 'Getting a view' do
183
+ it 'GET $database_name/_view/$view_name' do
184
+ @server.expects(:get).with("#{TestDatabase}/_view/my-view", {})
185
+ @database.view('my-view')
186
+ end
187
+
188
+ it 'uses the given parameters' do
189
+ @server.expects(:get).with(anything, :count => 100)
190
+ @database.view('my-view', :count => 100)
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,211 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ describe 'Server' do
4
+ setup do
5
+ @server = Couchy::Server.new('http://localhost:5984/')
6
+ end
7
+
8
+ it 'has an accessor on its uri' do
9
+ server = Couchy::Server.new('foo')
10
+ server.uri.to_s.should.equal 'foo'
11
+ end
12
+
13
+ describe 'Various utility methods' do
14
+ setup do
15
+ Couchy::Server.class_eval { public :uri_for, :json, :stringify_keys_and_jsonify_values }
16
+ @server = Couchy::Server.new('http://foo.org/')
17
+ end
18
+
19
+ specify '#json parse the given json string with the given options' do
20
+ JSON.expects(:parse).with('foo', :bar => :spam)
21
+ @server.send(:json, 'foo', :bar => :spam)
22
+ end
23
+
24
+ describe '#uri_for' do
25
+ setup do
26
+ @uri = stub('server uri joined with given path', :query_values= => '')
27
+ @server.uri.stubs(:join).returns(@uri)
28
+ end
29
+
30
+ it 'joins the given path with the URI of the server' do
31
+ @server.uri.expects(:join).with('bar/spam')
32
+ @server.uri_for('bar/spam')
33
+ end
34
+
35
+ it 'stringifys keys and jsonifys values of the given parameters' do
36
+ @server.expects(:stringify_keys_and_jsonify_values).with(:is => 'awesome').returns({})
37
+ @server.uri_for('group/home', {:is => 'awesome'})
38
+ end
39
+
40
+ it 'sets the query to the given parameters' do
41
+ params = {:foo => 'bar'}
42
+ @uri.expects(:query_values=).with('stringified keys')
43
+ @server.stubs(:stringify_keys_and_jsonify_values).with(params).returns('stringified keys')
44
+ @server.uri_for('dj/premier', params)
45
+ end
46
+
47
+ it 'do not set the query if no parameters' do
48
+ @uri.expects(:query_values=).never
49
+ @server.uri_for('primo')
50
+ end
51
+
52
+ it 'returns the resulting URI as a string' do
53
+ @uri.expects(:to_s).returns('resulting uri as a string')
54
+ @server.uri_for('supa/star').should.equal 'resulting uri as a string'
55
+ end
56
+ end
57
+
58
+ describe '#stringify_keys_and_jsonify_values' do
59
+ it 'stringifys keys' do
60
+ @server.stringify_keys_and_jsonify_values(:foo => 'bar').should.equal('foo' => 'bar')
61
+ end
62
+
63
+ it 'jsonifys value if key is "key"' do
64
+ @server.stringify_keys_and_jsonify_values(:key => {'foo' => 'bar'}).should.
65
+ equal('key' => '{"foo":"bar"}')
66
+ end
67
+
68
+ it 'jsonifys value if key is "startkey"' do
69
+ @server.stringify_keys_and_jsonify_values(:startkey => {'foo' => 'bar'}).should.
70
+ equal('startkey' => '{"foo":"bar"}')
71
+ end
72
+
73
+ it 'jsonifys value if key is "endkey"' do
74
+ @server.stringify_keys_and_jsonify_values(:endkey => {'foo' => 'bar'}).should.
75
+ equal('endkey' => '{"foo":"bar"}')
76
+ end
77
+ end
78
+ end
79
+
80
+ describe 'HTTP requests utility methods' do
81
+ describe 'GET' do
82
+ it "appends the given path to the server's URI" do
83
+ @server.stubs(:json)
84
+ RestClient.expects(:get).with('http://localhost:5984/foo/bar')
85
+ @server.get('foo/bar')
86
+ end
87
+
88
+ it 'appends the given parameters as the query string' do
89
+ @server.stubs(:json)
90
+ RestClient.expects(:get).with('http://localhost:5984/foo?bar=spam')
91
+ @server.get('foo', :bar => 'spam')
92
+ end
93
+
94
+ it 'parses the server response as json with :max_nesting set to false' do
95
+ RestClient.stubs(:get).returns('some json')
96
+ @server.expects(:json).with('some json', :max_nesting => false).returns([])
97
+ @server.get('give_me_some_json')
98
+ end
99
+
100
+ it 'do not parse the result as json if :no_json is specified' do
101
+ RestClient.stubs(:get)
102
+ @server.expects(:json).never
103
+ @server.get('foo', :no_json => true)
104
+ end
105
+ end
106
+
107
+ describe 'POST' do
108
+ setup do
109
+ @server.stubs(:json)
110
+ end
111
+
112
+ it "appends the given path to server's URI" do
113
+ RestClient.expects(:post).with('http://localhost:5984/a/b', nil, anything)
114
+ @server.post('a/b')
115
+ end
116
+
117
+ it 'appends the given parameters as the query string' do
118
+ RestClient.expects(:post).with('http://localhost:5984/foo?bar=spam', nil, anything)
119
+ @server.post('foo', nil, :bar => 'spam')
120
+ end
121
+
122
+ it 'jsonify the given body and post it' do
123
+ body = {:foo => 'bar'}
124
+ body.expects(:to_json).returns('some json')
125
+ RestClient.expects(:post).with(anything, 'some json', anything)
126
+ @server.post('foo', body)
127
+ end
128
+
129
+ it 'passes given headers to RestClient' do
130
+ RestClient.expects(:post).with(anything, anything, {'Content-Type' => 'application/json'})
131
+ @server.post('foo', nil, :headers => {'Content-Type' => 'application/json'})
132
+ end
133
+ end
134
+
135
+ describe 'PUT' do
136
+ setup do
137
+ @server.stubs(:json)
138
+ end
139
+
140
+ it "appends the given path to the server's URI" do
141
+ RestClient.expects(:put).with('http://localhost:5984/a/b', anything)
142
+ @server.put('a/b')
143
+ end
144
+
145
+ it 'jsonify and PUT the given body' do
146
+ body = {:foo => 'bar'}
147
+ body.expects(:to_json).returns('some json')
148
+ RestClient.expects(:put).with(anything, 'some json')
149
+ @server.put('foo', body)
150
+ end
151
+ end
152
+
153
+ describe 'DELETE' do
154
+ it "appends the given path to the server's URI" do
155
+ @server.stubs(:json).returns('')
156
+ RestClient.expects(:delete).with('http://localhost:5984/a/b')
157
+ @server.delete('a/b')
158
+ end
159
+
160
+ it 'appends the given parameters as the query string' do
161
+ @server.stubs(:json)
162
+ RestClient.expects(:delete).with('http://localhost:5984/foo/bar?a=b')
163
+ @server.delete('foo/bar', :a => :b)
164
+ end
165
+ end
166
+ end
167
+
168
+ describe 'Getting a list of all the databases' do
169
+ it 'GET _all_dbs' do
170
+ @server.expects(:get).with('_all_dbs')
171
+ @server.databases
172
+ end
173
+ end
174
+
175
+ describe 'Getting a database' do
176
+ it 'creates a new Database object with the given name and itselfs' do
177
+ Couchy::Database.expects(:new).with(@server, 'mydb')
178
+ @server.database('mydb')
179
+ end
180
+
181
+ it 'returns a Database object' do
182
+ @server.database('mydb').should.be.an.instance_of Couchy::Database
183
+ end
184
+ end
185
+
186
+ describe 'Getting info on the server' do
187
+ it 'GET the server URI' do
188
+ @server.expects(:get).with('/')
189
+ @server.info
190
+ end
191
+ end
192
+
193
+ describe 'Restarting the server' do
194
+ it 'POST _restart' do
195
+ @server.expects(:post).with('_restart')
196
+ @server.restart!
197
+ end
198
+ end
199
+
200
+ describe 'Creating a new database' do
201
+ it 'PUT to database_name' do
202
+ @server.expects(:put).with('mydb')
203
+ @server.create_db('mydb')
204
+ end
205
+
206
+ it 'returns a Database object' do
207
+ @server.stubs(:put)
208
+ @server.create_db('mydb').should.be.an.instance_of Couchy::Database
209
+ end
210
+ end
211
+ end