paginater 0.0.5

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,327 @@
1
+ require 'spec_helper'
2
+
3
+ describe Grape::Formatter::Paginater do
4
+
5
+ subject do
6
+ Class.new(Grape::API)
7
+ end
8
+
9
+ def app
10
+ subject
11
+ end
12
+
13
+ describe '#header' do
14
+ it 'is callable from within a block' do
15
+ subject.get('/hey') do
16
+ header 'X-Awesome', 'true'
17
+ "Awesome"
18
+ end
19
+
20
+ get '/hey'
21
+ last_response.headers['X-Awesome'].should == 'true'
22
+ end
23
+ end
24
+
25
+ describe '#headers' do
26
+ before do
27
+ subject.get('/headers') do
28
+ headers.to_json
29
+ end
30
+ end
31
+ it 'includes request headers' do
32
+ get '/headers'
33
+ JSON.parse(last_response.body).should == {
34
+ "Host" => "example.org",
35
+ "Cookie" => ""
36
+ }
37
+ end
38
+ it 'includes additional request headers' do
39
+ get '/headers', nil, { "HTTP_X_GRAPE_CLIENT" => "1" }
40
+ JSON.parse(last_response.body)["X-Grape-Client"].should == "1"
41
+ end
42
+ end
43
+
44
+ context "without paginater" do
45
+
46
+ before :each do
47
+ stuff = {:stuff => 'foo bar'}
48
+ end
49
+
50
+ it "sets itself in the env upon call" do
51
+ subject.get('/') do
52
+ 'Hello world.'
53
+ end
54
+ get '/'
55
+ last_request.env['api.endpoint'].should be_kind_of(Grape::Endpoint)
56
+ end
57
+
58
+ it "should work without paginater" do
59
+ subject.get('/') do
60
+ 'foo bar!'
61
+ end
62
+ get '/'
63
+ last_response.body.should eq 'foo bar!'
64
+ end
65
+
66
+ it "should not raise error about stuff" do
67
+ subject.format :json
68
+ subject.get '/home' do
69
+ stuff = {:stuff => 'foo bar'}
70
+ end
71
+ lambda do
72
+ get '/home'
73
+ end.should_not raise_error
74
+ get '/home'
75
+ last_response.body.should eq "{\"stuff\":\"foo bar\"}"
76
+ last_response.body.should include MultiJson.dump stuff
77
+ end
78
+
79
+ end
80
+
81
+ context "with the route_option :paginater => :simple" do
82
+
83
+ before :each do
84
+ subject.format :json
85
+ subject.formatter :json, Grape::Formatter::Paginater
86
+ stuff = {:stuff => 'foo bar'}
87
+ end
88
+
89
+ it "should respond with proper content-type" do
90
+ subject.get '/home', :paginater => :simple do
91
+ stuff = {:stuff => 'foo bar'}
92
+ end
93
+ get('/home?page=1')
94
+ last_response.headers['Content-Type'].should == 'application/json'
95
+ end
96
+
97
+ it 'rescues a specific error' do
98
+ subject.rescue_from Grape::Formatter::Paginater::Constants::PaginaterError do |e|
99
+ rack_response("rescued from #{e.class.name}", 500)
100
+ end
101
+ subject.get '/home', :paginater => :simple do
102
+ raise Grape::Formatter::Paginater::Constants::PaginaterError unless params[:page]
103
+ end
104
+ subject.get '/foo' do
105
+ raise 'foo_exception'
106
+ end
107
+ get '/home'
108
+ last_response.status.should eql 500
109
+ last_response.body.should == 'rescued from Grape::Formatter::Paginater::Constants::PaginaterError'
110
+ lambda do
111
+ get '/foo'
112
+ end.should raise_error
113
+ end
114
+
115
+ it 'should understand a missing page situation' do
116
+ subject.get '/home', :paginater => :simple do
117
+ params[:page]
118
+ stuff = {:stuff => 'foo bar'}
119
+ end
120
+ lambda do
121
+ get '/home'
122
+ end.should_not raise_error
123
+ last_response.status.should eql 500
124
+ last_response.body.should eq '{"error":"missing param"}'
125
+ end
126
+
127
+ it 'defaults the error formatter to format' do
128
+ subject.format :json
129
+ subject.rescue_from :all
130
+ subject.content_type :json, "application/json"
131
+ subject.content_type :foo, "text/foo"
132
+ subject.get '/exception' do
133
+ raise "rain!"
134
+ end
135
+ get '/exception.json'
136
+ last_response.body.should == '{"error":"rain!"}'
137
+ get '/exception.foo'
138
+ last_response.body.should == '{"error":"rain!"}'
139
+ end
140
+
141
+ it 'should work with the params requested' do
142
+ subject.format :json
143
+ subject.rescue_from :all
144
+ subject.get '/stuff', :paginater => :simple do
145
+ params[:page]
146
+ stuff = {:stuff => 'foo bar'}
147
+ end
148
+ get '/stuff?page=42'
149
+ last_response.body.should eq '{"error":"invalid page 42"}'
150
+ last_response.status.should eq 500
151
+ end
152
+
153
+ end
154
+
155
+ context "dealing with something that ... count" do
156
+
157
+ before :each do
158
+ subject.format :json
159
+ subject.formatter :json, Grape::Formatter::Paginater
160
+ subject.get '/foo', :paginater => :simple do
161
+ numbers(42)
162
+ end
163
+ end
164
+ it 'consider Array objects as paginable' do
165
+ get('/foo?page=11')
166
+ last_response.status.should eq 200
167
+ last_response.header.should include 'Link'
168
+ end
169
+ it 'paginate the body' do
170
+ get('/foo?page=11')
171
+ last_response.status.should eq 200
172
+ last_response.body.should include '10'
173
+ end
174
+ it 'paginate the body and understand size' do
175
+ get('/foo?page=3&size=3')
176
+ last_response.status.should eq 200
177
+ last_response.body.should_not include '5'
178
+ last_response.body.should include '6'
179
+ last_response.body.should include '8'
180
+ last_response.body.should_not include '9'
181
+ last_response.body.should include 6.upto(8).to_a.to_s.gsub(/\s/,'')
182
+ end
183
+ it 'set headers for pagination' do
184
+ get('/foo?page=3&size=3')
185
+ last_response.status.should eq 200
186
+ last_response.header.should include 'Link'
187
+ last_response.header['Link'].should include 'page=1'
188
+ last_response.header['Link'].should include 'next'
189
+ last_response.header['Link'].should include 'page=4'
190
+ last_response.header['Link'].should include 'prev'
191
+ last_response.header['Link'].should include 'page=2'
192
+ end
193
+ it 'do not mess with last pages' do
194
+ get('/foo?page=5&size=10')
195
+ last_response.status.should eq 200
196
+ last_response.header.should include 'Link'
197
+ last_response.header['Link'].should include 'prev'
198
+ last_response.header['Link'].should_not include 'next'
199
+ last_response.body.should_not include '39'
200
+ last_response.body.should include '40'
201
+ last_response.body.should include '42'
202
+ last_response.body.should_not include '43'
203
+ last_response.body.should include 41.upto(42).to_a.to_s.gsub(/[\[\s\]]/,'')
204
+ end
205
+ it 'do not mess with foo pages' do
206
+ get('/foo?page=42&size=42')
207
+ last_response.status.should eq 500
208
+ end
209
+
210
+ end
211
+
212
+ context "dealing with something that ... count but :txt" do
213
+
214
+ before :each do
215
+ subject.format :txt
216
+ subject.formatter :txt, Grape::Formatter::Paginater
217
+ subject.get '/foo', :paginater => :simple do
218
+ alphabet
219
+ end
220
+ end
221
+ it 'consider Array objects as paginable' do
222
+ get('/foo?page=11')
223
+ last_response.status.should eq 200
224
+ last_response.header['Link'].should include 'first'
225
+ end
226
+
227
+ it 'understand and return a txt' do
228
+ get('/foo?page=1&size=10')
229
+ last_response.body.should include "Alpha"
230
+ last_response.body.should_not include "Kilo"
231
+ last_response.header['Link'].should include "page=1"
232
+ last_response.body.split(',').count.should eq 10
233
+ end
234
+
235
+ end
236
+
237
+ context "set pagination headers" do
238
+
239
+ before :each do
240
+ subject.format :json
241
+ subject.formatter :json, Grape::Formatter::Paginater
242
+ subject.get '/foo', :paginater => :simple do
243
+ items(9)
244
+ end
245
+ end
246
+ it 'understand the first page' do
247
+ get('/foo?page=1')
248
+ last_response.status.should eq 200
249
+ last_response.header['Link'].should include 'page=1'
250
+ last_response.header['Link'].should include 'next'
251
+ last_response.header['Link'].should_not include 'prev'
252
+ end
253
+ it 'understand the last page' do
254
+ get('/foo?page=10')
255
+ last_response.status.should eq 200
256
+ last_response.header['Link'].should include 'prev'
257
+ last_response.header['Link'].should include 'page=9'
258
+ last_response.header['Link'].should_not include 'next'
259
+ end
260
+ it 'understand the last page with size' do
261
+ get('/foo?page=5&size=2')
262
+ last_response.status.should eq 200
263
+ last_response.header['Link'].should include 'prev'
264
+ last_response.header.should_not include 'next'
265
+ last_response.body.split(',').count.should eq 2
266
+ get('/foo?page=4&size=3')
267
+ last_response.status.should eq 200
268
+ last_response.header['Link'].should include 'prev'
269
+ last_response.header['Link'].should include 'page=3'
270
+ last_response.header.should_not include 'next'
271
+ last_response.body.split(',').count.should eq 1
272
+ end
273
+ it 'paginate the body' do
274
+ get('/foo?page=1')
275
+ last_response.status.should eq 200
276
+ last_response.body.should eq '["item 000"]'
277
+ get('/foo?page=10')
278
+ last_response.body.should eq '["item 009"]'
279
+ get('/foo?page=11')
280
+ last_response.status.should eq 500
281
+ get('/foo?page=3&size=3')
282
+ last_response.body.should eq '["item 006","item 007","item 008"]'
283
+ end
284
+
285
+ end
286
+
287
+ context "with the wrapped object" do
288
+
289
+ before :each do
290
+ subject.format :json
291
+ subject.formatter :json, Grape::Formatter::Paginater
292
+ subject.get '/foobar', :paginater => :wrapper do
293
+ items(42)
294
+ end
295
+ end
296
+ it "get something paginated" do
297
+ get('/foobar?page=1')
298
+ last_response.status.should eq 200
299
+ # deprecating....
300
+ last_response.header['Link'].should include 'page', 'next'
301
+ last_response.header.should_not include 'prev'
302
+ last_response.body.should include '["item 000"]'
303
+ last_response.body.should eq "{\"content\":[\"item 000\"],\"page\":1,\"size\":1,\"links\":null}"
304
+ get('/foobar?page=3&size=3')
305
+ last_response.body.should eq "{\"content\":[\"item 006\",\"item 007\",\"item 008\"],\"page\":3,\"size\":3,\"links\":null}"
306
+ end
307
+
308
+ end
309
+
310
+ context "put something in the cookies" do
311
+
312
+ before :each do
313
+ subject.format :json
314
+ subject.formatter :json, Grape::Formatter::Paginater
315
+ subject.get '/foobar', :paginater => :simple do
316
+ items(42)
317
+ end
318
+ end
319
+
320
+ it "count total_pages and original_count" do
321
+ get('/foobar?page=7&size=3')
322
+ last_response.header['Set-Cookie'].should include "7/14/43"
323
+ end
324
+
325
+ end
326
+
327
+ end # Grape::Formatter::Paginater
@@ -0,0 +1,165 @@
1
+ # spec/paginater/paginater_with_kaminari_spec.rb
2
+
3
+ require 'spec_helper'
4
+ require 'support/active_record_support'
5
+
6
+ if defined? ActiveRecord
7
+
8
+ describe Grape::Formatter::Paginater do
9
+
10
+ subject do
11
+ Class.new(Grape::API)
12
+ end
13
+
14
+ def app
15
+ subject
16
+ end
17
+
18
+ shared_examples_for 'the first page' do
19
+ it { should have(25).users }
20
+ its('first.name') { should == 'user001' }
21
+ end
22
+
23
+ shared_examples_for 'blank page' do
24
+ it { should have(0).users }
25
+ end
26
+
27
+ before :each do
28
+ 0.upto(999) {|i| User.create! :name => "user#{'%03d' % i}", :age => (i / 10)}
29
+ end
30
+
31
+ after :each do
32
+ User.destroy_all
33
+ end
34
+
35
+ context "with the kaminari amazing gem" do
36
+
37
+ before :each do
38
+ subject.format :json
39
+ subject.formatter :json, Grape::Formatter::Paginater
40
+ subject.get '/users', :paginater => :kaminari do
41
+ User.where("age > 0")
42
+ end
43
+ end
44
+
45
+ it "get something paginated" do
46
+ get('/users?page=42&size=10')
47
+ last_response.status.should eq 200
48
+ last_response.header['Link'].should include 'first', 'next'
49
+ last_response.header.should_not include 'prev'
50
+ last_response.body.should include '{"user":{"age":42,"id":425,"name":"user424"}}'
51
+ last_response.header['Link'].should include "{:url=>\"/users?page=1&size=10\", :rel=>\"first\"}"
52
+ last_response.header['Link'].should include "{:url=>\"/users?page=43&size=10\", :rel=>\"next\"}"
53
+ last_response.header['Link'].should include "{:url=>\"/users?page=41&size=10\", :rel=>\"prev\"}"
54
+ end
55
+
56
+ end
57
+
58
+ context "some features with kaminari" do
59
+
60
+ # let(:all_user_count) { User.all.count }
61
+
62
+ before :each do
63
+ subject.format :json
64
+ subject.formatter :json, Grape::Formatter::Paginater
65
+ subject.get '/users', :paginater => :kaminari do
66
+ User.where("age > -1")
67
+ end
68
+ end
69
+
70
+ it "get something paginated with body, headers and cookies" do
71
+ get('/users?page=1&size=10')
72
+ last_response.status.should eq 200
73
+ last_response.body.scan(/\"user\"/).flatten.count.should == 10
74
+ last_response.header['Set-Cookie'].should include "1/100/1000" #page/pages/count
75
+ last_response.header['Link'].should include '/users?page=2&size=10'
76
+ last_response.header['Link'].should_not include 'prev'
77
+ end
78
+
79
+ it "use the default size of 1" do
80
+ get('/users?page=1')
81
+ last_response.status.should eq 200
82
+ last_response.body.scan(/\"user\"/).flatten.count.should == 1
83
+ last_response.header['Set-Cookie'].should include "1/1000/1000"
84
+ last_response.header['Link'].should include '/users?page=2'
85
+ end
86
+
87
+ it "manage an exceeding size as .all" do
88
+ get('/users?page=1&size=9999')
89
+ last_response.status.should eq 200
90
+ last_response.body.scan(/\"user\"/).flatten.count.should == 1000
91
+ last_response.header['Set-Cookie'].should include "1/1/1000"
92
+ last_response.header['Link'].should_not include '/users?page=2'
93
+ end
94
+
95
+ end
96
+
97
+ context "with kaminari and an array (PaginatableArray)" do
98
+
99
+ before :each do
100
+ subject.format :json
101
+ subject.formatter :json, Grape::Formatter::Paginater
102
+ subject.get '/foobar', :paginater => :kaminari do
103
+ items(99)
104
+ end
105
+ end
106
+ it "get something paginated (with default size)" do
107
+ get('/foobar?page=1')
108
+ last_response.status.should eq 200
109
+ end
110
+ it "get something paginated" do
111
+ get('/foobar?page=1&size=10')
112
+ last_response.status.should eq 200
113
+ last_response.header['Link'].should include "{:url=>\"/foobar?page=1&size=10\", :rel=>\"first\"}"
114
+ last_response.header['Link'].should include "{:url=>\"/foobar?page=2&size=10\", :rel=>\"next\"}"
115
+ last_response.body.should include "item 009"
116
+ last_response.body.should_not include "item 010"
117
+ end
118
+ it "get something paginated with default size = 1" do
119
+ get('/foobar?page=100')
120
+ last_response.body.scan(/"(.*?)"/).flatten.count.should == 1
121
+ last_response.header['Link'].should_not include "next"
122
+ end
123
+ it "get something paginated with the size param" do
124
+ get('/foobar?page=10&size=10')
125
+ last_response.body.scan(/"(.*?)"/).flatten.count.should == 10
126
+ last_response.header['Link'].should_not include "next"
127
+ end
128
+ it "understand a non existing page" do
129
+ get('/foobar?page=11&size=10')
130
+ last_response.body.scan(/"(.*?)"/).flatten.count.should == 0
131
+ last_response.body.should == '[]'
132
+ # FIXME?
133
+ # p last_response.header['Link']
134
+ # p last_response.header['Set-Cookie']
135
+ end
136
+
137
+ end
138
+
139
+ context "with kaminari and an hash" do
140
+
141
+ before :each do
142
+ subject.format :json
143
+ subject.formatter :json, Grape::Formatter::Paginater
144
+ subject.get '/foobar', :paginater => :kaminari do
145
+ [{:foo => 'bar'},{:bar => 'foo'}]
146
+ end
147
+ end
148
+ it "get something paginated" do
149
+ get('/foobar?page=1')
150
+ last_response.status.should eq 200
151
+ last_response.body.should include "[{\"foo\":\"bar\"}]"
152
+ last_response.header['Link'].should include "{:url=>\"/foobar?page=1\", :rel=>\"first\"}"
153
+ end
154
+ it "discern errors and override size with 1 if necessary" do
155
+ get('/foobar?page=1&size=0')
156
+ last_response.status.should eq 200
157
+ last_response.body.should == "[{\"foo\":\"bar\"}]"
158
+ end
159
+
160
+ end
161
+
162
+ end # Grape::Formatter::Paginater
163
+
164
+ end
165
+