paginater 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+