couch_docs 1.2.1 → 1.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.
@@ -0,0 +1,170 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe CouchDocs::CommandLine do
4
+ it "should be able to run a single instance of a command line" do
5
+ CouchDocs::CommandLine.
6
+ should_receive(:new).
7
+ with('foo', 'bar').
8
+ and_return(mock("Command Line").as_null_object)
9
+
10
+ CouchDocs::CommandLine.run('foo', 'bar')
11
+ end
12
+
13
+ it "should run the command line instance" do
14
+ command_line = mock("Command Line").as_null_object
15
+ command_line.
16
+ should_receive(:run)
17
+
18
+ CouchDocs::CommandLine.stub!(:new).and_return(command_line)
19
+
20
+ CouchDocs::CommandLine.run('foo', 'bar')
21
+ end
22
+
23
+ context "an instance that dumps a CouchDB database" do
24
+ it "should dump CouchDB documents from uri to dir when run" do
25
+ @it = CouchDocs::CommandLine.new(['dump', 'uri', 'dir'])
26
+
27
+ CouchDocs.
28
+ should_receive(:dump).
29
+ with("uri", "dir", nil)
30
+
31
+ @it.run
32
+ end
33
+
34
+ it "should be able to dump only design documents" do
35
+ @it = CouchDocs::CommandLine.new(['dump', 'uri', 'dir', '-d'])
36
+
37
+ CouchDocs.
38
+ should_receive(:dump).
39
+ with("uri", "dir", :design)
40
+
41
+ @it.run
42
+ end
43
+
44
+ it "should be able to dump only regular documents" do
45
+ @it = CouchDocs::CommandLine.new(['dump', 'uri', 'dir', '-D'])
46
+
47
+ CouchDocs.
48
+ should_receive(:dump).
49
+ with("uri", "dir", :doc)
50
+
51
+ @it.run
52
+ end
53
+
54
+ it "should be an initial add if everything is an add" do
55
+ @it = CouchDocs::CommandLine.new(['push', 'uri'])
56
+ args = [mock(:type => :added),
57
+ mock(:type => :added)]
58
+ @it.should be_initial_add(args)
59
+ end
60
+
61
+ it "should not be an initial add if something is not an add" do
62
+ @it = CouchDocs::CommandLine.new(['push', 'uri'])
63
+ args = [mock(:type => :foo),
64
+ mock(:type => :added)]
65
+ @it.should_not be_initial_add(args)
66
+ end
67
+
68
+ it "should be a design docs update if something changes in _design" do
69
+ @it = CouchDocs::CommandLine.new(['push', 'uri'])
70
+ args = [mock(:path => "foo"),
71
+ mock(:path => "_design")]
72
+ @it.should be_design_doc_update(args)
73
+ end
74
+
75
+ it "should know document updates" do
76
+ @it = CouchDocs::CommandLine.new(['push', 'uri'])
77
+ doc_update = mock(:path => "foo")
78
+ args = [doc_update,
79
+ mock(:path => "_design")]
80
+
81
+ @it.
82
+ documents(args).
83
+ should == [doc_update]
84
+ end
85
+
86
+
87
+ context "updates on the filesystem" do
88
+ before(:each) do
89
+ @args = mock("args")
90
+ @it = CouchDocs::CommandLine.new(%w(push uri dir))
91
+ end
92
+ it "should only update design docs if only local design docs have changed" do
93
+ CouchDocs.
94
+ should_receive(:put_dir)
95
+
96
+ @it.stub!(:initial_add?).and_return(true)
97
+ @it.directory_watcher_update(@args)
98
+ end
99
+ context "not an inital add" do
100
+ before(:each) do
101
+ @it.stub!(:initial_add?).and_return(false)
102
+ @it.stub!(:design_doc_update?).and_return(false)
103
+ @it.stub!(:documents).and_return([])
104
+ CouchDocs.stub!(:put_design_dir)
105
+ end
106
+ it "should update design docs if there are design document updates" do
107
+ CouchDocs.
108
+ should_receive(:put_design_dir)
109
+
110
+ @it.stub!(:design_doc_update?).and_return(true)
111
+ @it.directory_watcher_update(@args)
112
+ end
113
+ it "should update documents (if any)" do
114
+ file_mock = mock("File", :path => "/foo")
115
+ @it.stub!(:documents).and_return([file_mock])
116
+
117
+ CouchDocs.
118
+ should_receive(:put_file).
119
+ with("uri", "/foo")
120
+
121
+ @it.directory_watcher_update(@args)
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ context "pushing" do
128
+ before(:each) do
129
+ CouchDocs.stub!(:put_dir)
130
+
131
+ @dw = mock("Directory Watcher").as_null_object
132
+ DirectoryWatcher.stub!(:new).and_return(@dw)
133
+ end
134
+
135
+ it "should know watch" do
136
+ @it = CouchDocs::CommandLine.new(%w(push uri dir -w))
137
+ @it.options[:watch].should be_true
138
+ end
139
+
140
+ it "should run once normally" do
141
+ @dw.should_receive(:run_once)
142
+
143
+ @it = CouchDocs::CommandLine.new(%w(push uri dir))
144
+ @it.run
145
+ end
146
+
147
+ it "should start a watcher with -w" do
148
+ @dw.should_receive(:start)
149
+
150
+ @it = CouchDocs::CommandLine.new(%w(push uri dir -w))
151
+ @it.stub!(:active?).and_return(false)
152
+ @it.run
153
+ end
154
+ end
155
+
156
+ context "an instance that uploads to a CouchDB database" do
157
+ before(:each) do
158
+ @it = CouchDocs::CommandLine.new(['load', 'dir', 'uri'])
159
+ end
160
+
161
+ it "should load CouchDB documents from dir to uri when run" do
162
+ CouchDocs.
163
+ should_receive(:put_dir).
164
+ with("uri", "dir")
165
+
166
+ @it.run
167
+ end
168
+ end
169
+
170
+ end
@@ -0,0 +1,197 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe CouchDocs::DesignDirectory do
4
+ it "should require a root directory for instantiation" do
5
+ lambda { CouchDocs::DesignDirectory.new }.
6
+ should raise_error
7
+
8
+ lambda { CouchDocs::DesignDirectory.new("foo") }.
9
+ should raise_error
10
+
11
+ lambda { CouchDocs::DesignDirectory.new("fixtures/_design")}.
12
+ should_not raise_error
13
+ end
14
+
15
+ it "should convert arrays into deep hashes" do
16
+ CouchDocs::DesignDirectory.
17
+ a_to_hash(%w{a b c d}).
18
+ should == {
19
+ 'a' => {
20
+ 'b' => {
21
+ 'c' => 'd'
22
+ }
23
+ }
24
+ }
25
+ end
26
+
27
+ context "a valid directory" do
28
+ before(:each) do
29
+ @it = CouchDocs::DesignDirectory.new("fixtures/_design")
30
+ end
31
+
32
+ it "should list dirs, basename and contents of a js file" do
33
+ @it.expand_file("fixtures/_design/a/b/c.js").
34
+ should == ['a', 'b', 'c', 'function(doc) { return true; }']
35
+ end
36
+
37
+ it "should list dirs, basename and contents of a json file" do
38
+ @it.expand_file("fixtures/_design/a/e.json").
39
+ should == ['a', 'e', [{"one" => "2"}]]
40
+ end
41
+
42
+ it "should assemble all documents into a single docs structure" do
43
+ @it.to_hash['a'].
44
+ should == {
45
+ 'b' => {
46
+ 'c' => 'function(doc) { return true; }',
47
+ 'd' => 'function(doc) { return true; }'
48
+ },
49
+ 'e' => [{"one" => "2"}]
50
+ }
51
+ end
52
+
53
+ it "should process code macros when assembling" do
54
+ @it.to_hash['x'].
55
+ should == {
56
+ 'z' =>
57
+ "// !begin code foo.js\n" +
58
+ "function foo () { return \"foo\"; }\n" +
59
+ "// !end code foo.js\n" +
60
+ "function bar () { return \"bar\"; }\n"
61
+ }
62
+ end
63
+
64
+ it "should ignore macro escape sequence when reading JSON" do
65
+ @it.to_hash['j'].
66
+ should == {'q' => ["!code foo.js"]}
67
+ end
68
+
69
+ it "should work with absolute !code paths"
70
+
71
+ it "should replace !code macros with the contents of the referenced file in lib" do
72
+ @it.stub!(:read_from_lib).and_return("awesome javascript")
73
+
74
+ @it.
75
+ process_code_macro(" // !code foo/bar.js ").
76
+ should =~ /awesome javascript/
77
+ end
78
+
79
+ it "should not affect normal lines when processing macros" do
80
+ @it.
81
+ process_code_macro(" var foo = 'bar'; ").
82
+ should == " var foo = 'bar'; "
83
+ end
84
+
85
+ it "should find files with relative paths in __lib" do
86
+ File.
87
+ should_receive(:read).
88
+ with("fixtures/_design/__lib/foo.js")
89
+
90
+ @it.read_from_lib("foo.js")
91
+ end
92
+
93
+ end
94
+
95
+ context "saving a JSON attribute" do
96
+ before(:each) do
97
+ @it = CouchDocs::DesignDirectory.new("/tmp")
98
+
99
+ FileUtils.stub!(:mkdir_p)
100
+ @file = mock("File").as_null_object
101
+ File.stub!(:new).and_return(@file)
102
+ end
103
+
104
+ it "should not mangle json valued attributes" do
105
+ @file.
106
+ should_receive(:write).
107
+ with(%{["bar","baz"]})
108
+
109
+ @it.save_js(nil, "_design/foo", { "foo" => ["bar","baz"] })
110
+ end
111
+
112
+ it "should save in a .json file" do
113
+ File.
114
+ should_receive(:new).
115
+ with("/tmp/_design/foo/foo.json", "w+").
116
+ and_return(@file)
117
+
118
+ @it.save_js(nil, "_design/foo", { "foo" => ["bar","baz"] })
119
+ end
120
+ end
121
+
122
+ context "saving a JS attribute" do
123
+ before(:each) do
124
+ @it = CouchDocs::DesignDirectory.new("/tmp")
125
+
126
+ FileUtils.stub!(:mkdir_p)
127
+ @file = mock("File").as_null_object
128
+ File.stub!(:new).and_return(@file)
129
+ end
130
+
131
+ it "should not store _id" do
132
+ File.
133
+ should_not_receive(:new).
134
+ with("/tmp/_design/foo/_id.js", "w+")
135
+
136
+ @it.save_js(nil, "_design/foo", { "_id" => "_design/foo"})
137
+ end
138
+
139
+ it "should create map the design document attribute to the filesystem" do
140
+ FileUtils.
141
+ should_receive(:mkdir_p).
142
+ with("/tmp/_design/foo")
143
+
144
+ @it.save_js("_design/foo", "bar", "json")
145
+ end
146
+
147
+ it "should store the attribute to the filesystem" do
148
+ File.
149
+ should_receive(:new).
150
+ with("/tmp/_design/foo/bar.js", "w+")
151
+
152
+ @it.save_js("_design/foo", "bar", "json")
153
+ end
154
+
155
+ it "should store hash values to the filesystem" do
156
+ File.
157
+ should_receive(:new).
158
+ with("/tmp/_design/foo/bar/baz.js", "w+")
159
+
160
+ @it.save_js("_design/foo", "bar", { "baz" => "json" })
161
+ end
162
+
163
+ it "should store the attribute to the filesystem" do
164
+ @file.
165
+ should_receive(:write).
166
+ with("json")
167
+
168
+ @it.save_js("_design/foo", "bar", "json")
169
+ end
170
+
171
+ it "should store the attributes with slashes to the filesystem" do
172
+ File.
173
+ should_receive(:new).
174
+ with("/tmp/_design/foo/bar%2Fbaz.js", "w+")
175
+
176
+ @it.save_js("_design/foo", "bar/baz", "json")
177
+ end
178
+
179
+ it "should strip lib code when dumping" do
180
+ js = <<_JS
181
+ // !begin code foo.js
182
+ function foo () { return 'foo'; }
183
+ // !end code foo.js
184
+ // !begin code bar.js
185
+ function bar () { return 'bar'; }
186
+ // !end code bar.js
187
+ function baz () { return 'baz'; }
188
+ _JS
189
+
190
+ @it.
191
+ remove_code_macros(js).
192
+ should == "// !code foo.js\n" +
193
+ "// !code bar.js\n" +
194
+ "function baz () { return 'baz'; }\n"
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,212 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe CouchDocs::DocumentDirectory do
4
+ it "should require a root directory for instantiation" do
5
+ lambda { CouchDocs::DocumentDirectory.new }.
6
+ should raise_error
7
+
8
+ lambda { CouchDocs::DocumentDirectory.new("foo") }.
9
+ should raise_error
10
+
11
+ lambda { CouchDocs::DocumentDirectory.new("fixtures")}.
12
+ should_not raise_error
13
+ end
14
+
15
+ context "a valid directory" do
16
+ before(:each) do
17
+ @it = CouchDocs::DocumentDirectory.new("fixtures")
18
+ end
19
+
20
+ it "should be able to iterate over the documents" do
21
+ everything = []
22
+ @it.each_document do |name, contents|
23
+ everything << [name, contents]
24
+ end
25
+ everything.
26
+ should include ['bar', {"bar" => "2"}]
27
+
28
+ everything.
29
+ should include ['foo', {"foo" => "1"}]
30
+ end
31
+
32
+ it "should be able to store a document" do
33
+ file = mock("File", :write => 42, :close => true)
34
+ File.
35
+ should_receive(:new).
36
+ with("fixtures/foo.json", "w+").
37
+ and_return(file)
38
+
39
+ @it.store_document({'_id' => 'foo'})
40
+ end
41
+
42
+ it "should be able to save a document as JSON" do
43
+ file = mock("File", :close => true)
44
+ File.stub!(:new).and_return(file)
45
+
46
+ file.should_receive(:write).with(%Q|{"_id":"foo"}|)
47
+
48
+ @it.store_document({'_id' => 'foo'})
49
+ end
50
+
51
+ context "pushing attachments to CouchDB" do
52
+ before(:each) do
53
+ @spacer_b64 = "R0lGODlhAQABAPcAAAAAAIAAAACAAICAAAAAgIAAgACAgICAgMDAwP8AAAD/AP//AAAA//8A/wD//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMwAAZgAAmQAAzAAA/wAzAAAzMwAzZgAzmQAzzAAz/wBmAABmMwBmZgBmmQBmzABm/wCZAACZMwCZZgCZmQCZzACZ/wDMAADMMwDMZgDMmQDMzADM/wD/AAD/MwD/ZgD/mQD/zAD//zMAADMAMzMAZjMAmTMAzDMA/zMzADMzMzMzZjMzmTMzzDMz/zNmADNmMzNmZjNmmTNmzDNm/zOZADOZMzOZZjOZmTOZzDOZ/zPMADPMMzPMZjPMmTPMzDPM/zP/ADP/MzP/ZjP/mTP/zDP//2YAAGYAM2YAZmYAmWYAzGYA/2YzAGYzM2YzZmYzmWYzzGYz/2ZmAGZmM2ZmZmZmmWZmzGZm/2aZAGaZM2aZZmaZmWaZzGaZ/2bMAGbMM2bMZmbMmWbMzGbM/2b/AGb/M2b/Zmb/mWb/zGb//5kAAJkAM5kAZpkAmZkAzJkA/5kzAJkzM5kzZpkzmZkzzJkz/5lmAJlmM5lmZplmmZlmzJlm/5mZAJmZM5mZZpmZmZmZzJmZ/5nMAJnMM5nMZpnMmZnMzJnM/5n/AJn/M5n/Zpn/mZn/zJn//8wAAMwAM8wAZswAmcwAzMwA/8wzAMwzM8wzZswzmcwzzMwz/8xmAMxmM8xmZsxmmcxmzMxm/8yZAMyZM8yZZsyZmcyZzMyZ/8zMAMzMM8zMZszMmczMzMzM/8z/AMz/M8z/Zsz/mcz/zMz///8AAP8AM/8AZv8Amf8AzP8A//8zAP8zM/8zZv8zmf8zzP8z//9mAP9mM/9mZv9mmf9mzP9m//+ZAP+ZM/+ZZv+Zmf+ZzP+Z///MAP/MM//MZv/Mmf/MzP/M////AP//M///Zv//mf//zP///yH5BAEAABAALAAAAAABAAEAAAgEALkFBAA7"
54
+ end
55
+
56
+ it "should connect attachments by sub-directory name (foo.json => foo/)" do
57
+ @it.stub!(:mime_type)
58
+
59
+ everything = []
60
+ @it.each_document do |name, contents|
61
+ everything << [name, contents]
62
+ end
63
+
64
+ everything.
65
+ should include(['baz_with_attachments',
66
+ {'baz' => '3',
67
+ "_attachments" => { "spacer.gif" => {"data" => @spacer_b64} } }])
68
+ end
69
+ it "should mime 64 encode attachments" do
70
+ # covered above
71
+ end
72
+ it "should ignore non-file attachments" do
73
+ # covered above
74
+ end
75
+
76
+ context "infering mime type" do
77
+ before(:each) do
78
+ File.stub!(:read).and_return("asdf")
79
+ Base64.stub!(:encode64).and_return("asdf")
80
+ end
81
+
82
+ it "should guess gif mime type" do
83
+ @it.file_as_attachment("spacer.gif").
84
+ should == {
85
+ "data" => "asdf",
86
+ "content_type" => "image/gif"
87
+ }
88
+ end
89
+
90
+ it "should guess jpeg mime type" do
91
+ @it.file_as_attachment("spacer.jpg").
92
+ should == {
93
+ "data" => "asdf",
94
+ "content_type" => "image/jpeg"
95
+ }
96
+ end
97
+
98
+ it "should guess png mime type" do
99
+ @it.file_as_attachment("spacer.png").
100
+ should == {
101
+ "data" => "asdf",
102
+ "content_type" => "image/png"
103
+ }
104
+ end
105
+
106
+ it "should default to no mime type" do
107
+ @it.file_as_attachment("spacer.foo").
108
+ should == {
109
+ "data" => "asdf"
110
+ }
111
+ end
112
+ end
113
+
114
+ it "should give precedence to filesystem attachments" do
115
+ @it.stub!(:mime_type)
116
+
117
+ JSON.stub!(:parse).
118
+ and_return({ "baz" => "3",
119
+ "_attachments" => {
120
+ "spacer.gif" => "asdf",
121
+ "baz.jpg" => "asdf"
122
+ }
123
+ })
124
+
125
+ everything = []
126
+ @it.each_document do |name, contents|
127
+ everything << [name, contents]
128
+ end
129
+
130
+ everything.
131
+ should include(['baz_with_attachments',
132
+ {'baz' => '3',
133
+ "_attachments" => { "spacer.gif" => {"data" => @spacer_b64}, "baz.jpg" => "asdf" } }])
134
+ end
135
+
136
+ end
137
+ context "dump attachments from CouchDB" do
138
+ before(:each) do
139
+ FileUtils.stub!(:mkdir_p)
140
+ end
141
+
142
+ it "should store attachments" do
143
+ file = mock("File").as_null_object
144
+ File.stub!(:new).and_return(file)
145
+
146
+ @it.
147
+ should_receive(:store_attachments).
148
+ with('foo', 'bar')
149
+
150
+ @it.store_document({'_id' => 'foo',
151
+ '_attachments' => 'bar'})
152
+ end
153
+
154
+ context "storing attachments" do
155
+ before(:each) do
156
+ @attachments = { 'foo.txt' => { 'data' => 'attachment data' } }
157
+ end
158
+
159
+ it "should make a directory to hold the attachments" do
160
+ @it.
161
+ should_receive(:make_attachment_dir).
162
+ with('foo')
163
+
164
+ @it.stub!(:save_attachment)
165
+ @it.store_attachments('foo', @attachments)
166
+ end
167
+
168
+ it "should create a sub-directory with document ID" do
169
+ FileUtils.
170
+ should_receive(:mkdir_p).
171
+ with("fixtures/foo")
172
+
173
+ @it.stub!(:save_attachment)
174
+ @it.make_attachment_dir('foo')
175
+ end
176
+
177
+ it "should save attachments to the filesystem" do
178
+ @it.
179
+ should_receive(:save_attachment).
180
+ with('foo', 'foo.txt', 'attachment data')
181
+
182
+ @it.stub!(:save_attachment)
183
+ @it.store_attachments('foo', @attachments)
184
+ end
185
+
186
+ it "should dump with native encoding (non-mime64)" do
187
+ file = mock("File").as_null_object
188
+ File.stub!(:new).and_return(file)
189
+
190
+ file.
191
+ should_receive(:write)
192
+
193
+ @it.save_attachment('foo', 'foo.txt', 'ZGF0YQ==')
194
+ end
195
+ end
196
+
197
+ it "should not include the attachments attribute" do
198
+ file = mock("File", :close => true)
199
+ File.stub!(:new).and_return(file)
200
+
201
+ file.
202
+ should_receive(:write).
203
+ with('{"_id":"foo"}')
204
+
205
+ @it.stub!(:store_attachments)
206
+
207
+ @it.store_document({'_id' => 'foo',
208
+ '_attachments' => 'foo'})
209
+ end
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,98 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe CouchDocs::Store do
4
+ it "should require a CouchDB URL Root for instantiation" do
5
+ lambda { CouchDocs::Store.new }.
6
+ should raise_error
7
+
8
+ lambda { CouchDocs::Store.new("uri") }.
9
+ should_not raise_error
10
+ end
11
+
12
+ context "a valid store" do
13
+ before(:each) do
14
+ @it = CouchDocs::Store.new("uri")
15
+
16
+ @hash = {
17
+ 'a' => {
18
+ 'b' => {
19
+ 'c' => 'function(doc) { return true; }'
20
+ }
21
+ }
22
+ }
23
+ end
24
+
25
+ it "should be able to put a new document" do
26
+ CouchDocs::Store.
27
+ should_receive(:put).
28
+ with("uri", { })
29
+
30
+ CouchDocs::Store.put!("uri", { })
31
+ end
32
+
33
+ it "should delete existing docs if first put fails" do
34
+ CouchDocs::Store.
35
+ stub!(:put).
36
+ and_raise(RestClient::RequestFailed)
37
+
38
+ CouchDocs::Store.
39
+ should_receive(:delete_and_put).
40
+ with("uri", { })
41
+
42
+ CouchDocs::Store.put!("uri", { })
43
+ end
44
+
45
+ it "should be able to delete and put" do
46
+ CouchDocs::Store.
47
+ should_receive(:delete).
48
+ with("uri")
49
+
50
+ CouchDocs::Store.
51
+ should_receive(:put).
52
+ with("uri", { })
53
+
54
+ CouchDocs::Store.delete_and_put("uri", { })
55
+ end
56
+
57
+ it "should be able to load a hash into design docs" do
58
+ RestClient.
59
+ should_receive(:put).
60
+ with("uri/_design/a",
61
+ '{"b":{"c":"function(doc) { return true; }"}}',
62
+ :content_type => 'application/json')
63
+ @it.put_design_documents(@hash)
64
+ end
65
+
66
+ it "should be able to retrieve an existing document" do
67
+ RestClient.
68
+ stub!(:get).
69
+ and_return('{"_rev":"1234"}')
70
+
71
+ CouchDocs::Store.get("uri").should == { '_rev' => "1234" }
72
+ end
73
+
74
+ it "should be able to delete an existing document" do
75
+ CouchDocs::Store.stub!(:get).and_return({ '_rev' => '1234' })
76
+
77
+ RestClient.
78
+ should_receive(:delete).
79
+ with("uri?rev=1234")
80
+
81
+ CouchDocs::Store.delete("uri")
82
+ end
83
+
84
+ it "should be able to load each document" do
85
+ CouchDocs::Store.stub!(:get).
86
+ with("uri/_all_docs").
87
+ and_return({ "total_rows" => 2,
88
+ "offset" => 0,
89
+ "rows" => [{"id"=>"1", "value"=>{}, "key"=>"1"},
90
+ {"id"=>"2", "value"=>{}, "key"=>"2"}]})
91
+
92
+ CouchDocs::Store.stub!(:get).with("uri/1?attachments=true")
93
+ CouchDocs::Store.should_receive(:get).with("uri/2?attachments=true")
94
+
95
+ @it.each { }
96
+ end
97
+ end
98
+ end