folio-pagination 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/.gitignore +17 -0
  2. data/.travis.yml +3 -0
  3. data/Gemfile +16 -0
  4. data/Guardfile +5 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +235 -0
  7. data/Rakefile +11 -0
  8. data/folio-pagination.gemspec +27 -0
  9. data/lib/folio/core_ext/enumerable.rb +51 -0
  10. data/lib/folio/invalid_page.rb +5 -0
  11. data/lib/folio/ordinal/page.rb +107 -0
  12. data/lib/folio/ordinal.rb +33 -0
  13. data/lib/folio/page.rb +86 -0
  14. data/lib/folio/per_page.rb +15 -0
  15. data/lib/folio/rails.rb +35 -0
  16. data/lib/folio/version.rb +3 -0
  17. data/lib/folio/will_paginate/active_record.rb +132 -0
  18. data/lib/folio/will_paginate/collection.rb +19 -0
  19. data/lib/folio/will_paginate/view_helpers/action_view.rb +10 -0
  20. data/lib/folio/will_paginate/view_helpers/link_renderer.rb +54 -0
  21. data/lib/folio/will_paginate/view_helpers/link_renderer_base.rb +44 -0
  22. data/lib/folio/will_paginate/view_helpers.rb +57 -0
  23. data/lib/folio-pagination.rb +3 -0
  24. data/lib/folio.rb +84 -0
  25. data/test/folio/core_ext/enumerable_test.rb +55 -0
  26. data/test/folio/ordinal/page_test.rb +173 -0
  27. data/test/folio/ordinal_test.rb +57 -0
  28. data/test/folio/page_test.rb +198 -0
  29. data/test/folio/per_page_test.rb +49 -0
  30. data/test/folio/rails_test.rb +15 -0
  31. data/test/folio/version_test.rb +8 -0
  32. data/test/folio/will_paginate/active_record_test.rb +118 -0
  33. data/test/folio/will_paginate/collection_test.rb +43 -0
  34. data/test/folio/will_paginate/view_helpers/link_renderer_base_test.rb +58 -0
  35. data/test/folio/will_paginate/view_helpers/link_renderer_test.rb +58 -0
  36. data/test/folio/will_paginate/view_helpers_test.rb +49 -0
  37. data/test/folio_test.rb +192 -0
  38. data/test/setup/active_record.rb +13 -0
  39. metadata +133 -0
@@ -0,0 +1,198 @@
1
+ require 'minitest/autorun'
2
+ require 'folio/page'
3
+ require 'folio'
4
+
5
+ describe Folio::Page do
6
+ before do
7
+ @page = Folio::Page.create
8
+ end
9
+
10
+ describe "ordinal_pages" do
11
+ it "should have ordinal_pages accessors" do
12
+ assert_respond_to @page, :ordinal_pages
13
+ assert_respond_to @page, :ordinal_pages=
14
+ assert_respond_to @page, :ordinal_pages?
15
+ end
16
+
17
+ it "should mutate with ordinal_pages=" do
18
+ @page.ordinal_pages = true
19
+ @page.ordinal_pages.must_equal true
20
+ end
21
+
22
+ it "should alias reader as predicate" do
23
+ @page.ordinal_pages = true
24
+ @page.ordinal_pages?.must_equal true
25
+ end
26
+ end
27
+
28
+ describe "current_page" do
29
+ it "should have current_page accessors" do
30
+ assert_respond_to @page, :current_page
31
+ assert_respond_to @page, :current_page=
32
+ end
33
+
34
+ it "should mutate with current_page=" do
35
+ @page.current_page = 3
36
+ @page.current_page.must_equal 3
37
+ end
38
+ end
39
+
40
+ describe "per_page" do
41
+ it "should have per_page accessors" do
42
+ assert_respond_to @page, :per_page
43
+ assert_respond_to @page, :per_page=
44
+ end
45
+
46
+ it "should mutate with per_page=" do
47
+ @page.per_page = 3
48
+ @page.per_page.must_equal 3
49
+ end
50
+
51
+ it "should default to Folio.per_page" do
52
+ was = Folio.per_page
53
+ Folio.per_page = 100
54
+ @page.per_page.must_equal Folio.per_page
55
+ Folio.per_page = was
56
+ end
57
+ end
58
+
59
+ describe "first_page" do
60
+ it "should have first_page accessors" do
61
+ assert_respond_to @page, :first_page
62
+ assert_respond_to @page, :first_page=
63
+ end
64
+
65
+ it "should mutate with first_page=" do
66
+ @page.first_page = 3
67
+ @page.first_page.must_equal 3
68
+ end
69
+ end
70
+
71
+ describe "last_page" do
72
+ it "should have last_page accessors" do
73
+ assert_respond_to @page, :last_page
74
+ assert_respond_to @page, :last_page=
75
+ end
76
+
77
+ it "should mutate with last_page= when next_page is non-nil" do
78
+ @page.next_page = 3
79
+ @page.last_page = 5
80
+ @page.last_page.must_equal 5
81
+ end
82
+
83
+ it "should default last_page=nil if unset and next_page is non-nil" do
84
+ @page.current_page = 2
85
+ @page.next_page = 3
86
+ @page.last_page.must_be_nil
87
+ end
88
+
89
+ it "should default last_page=current_page if unset and next_page is nil" do
90
+ end
91
+
92
+ it "should have last_page=current_page if next_page is nil, even if explicitly set" do
93
+ @page.current_page = 2
94
+ @page.last_page.must_equal 2
95
+
96
+ @page.last_page = 4
97
+ @page.last_page.must_equal 2
98
+
99
+ @page.last_page = nil
100
+ @page.last_page.must_equal 2
101
+ end
102
+ end
103
+
104
+ describe "next_page" do
105
+ it "should have next_page accessors" do
106
+ assert_respond_to @page, :next_page
107
+ assert_respond_to @page, :next_page=
108
+ end
109
+
110
+ it "should mutate with next_page=" do
111
+ @page.next_page = 3
112
+ @page.next_page.must_equal 3
113
+ end
114
+ end
115
+
116
+ describe "previous_page" do
117
+ it "should have previous_page accessors" do
118
+ assert_respond_to @page, :previous_page
119
+ assert_respond_to @page, :previous_page=
120
+ end
121
+
122
+ it "should mutate with previous_page=" do
123
+ @page.previous_page = 3
124
+ @page.previous_page.must_equal 3
125
+ end
126
+ end
127
+
128
+ describe "total_entries" do
129
+ it "should have total_entries accessors" do
130
+ assert_respond_to @page, :total_entries
131
+ assert_respond_to @page, :total_entries=
132
+ end
133
+
134
+ it "should mutate with total_entries=" do
135
+ @page.total_entries = 3
136
+ @page.total_entries.must_equal 3
137
+ end
138
+ end
139
+
140
+ describe "total_pages" do
141
+ before do
142
+ @page.total_entries = 10
143
+ @page.per_page = 5
144
+ end
145
+
146
+ it "should be nil if total_entries is nil" do
147
+ @page.total_entries = nil
148
+ @page.total_pages.must_be_nil
149
+ end
150
+
151
+ it "should be nil if per_page is 0" do
152
+ @page.per_page = 0
153
+ @page.total_pages.must_be_nil
154
+ end
155
+
156
+ it "should be 1 if total_entries is 0" do
157
+ @page.total_entries = 0
158
+ @page.total_pages.must_equal 1
159
+ end
160
+
161
+ it "should be total_entries/per_page if evenly divisible" do
162
+ @page.total_pages.must_equal 2
163
+ end
164
+
165
+ it "should round up if not evenly divisible" do
166
+ @page.per_page = 3
167
+ @page.total_pages.must_equal 4
168
+ end
169
+ end
170
+
171
+ describe "decorate" do
172
+ before do
173
+ @page = Folio::Page.decorate([])
174
+ end
175
+
176
+ it "should add page methods to the object" do
177
+ assert_respond_to @page, :current_page
178
+ end
179
+
180
+ it "should preserve other methods on the object" do
181
+ assert_respond_to @page, :each
182
+ end
183
+ end
184
+
185
+ describe "create" do
186
+ before do
187
+ @page = Folio::Page.create
188
+ end
189
+
190
+ it "should be an Array at heart" do
191
+ @page.must_be :is_a?, Array
192
+ end
193
+
194
+ it "should be decorated as a page" do
195
+ assert_respond_to @page, :current_page
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,49 @@
1
+ require 'minitest/autorun'
2
+ require 'folio/per_page'
3
+ require 'folio'
4
+
5
+ describe Folio::PerPage do
6
+ before do
7
+ @klass = Class.new{ include Folio::PerPage }
8
+ @object = @klass.new
9
+ end
10
+
11
+ describe "default_per_page" do
12
+ it "should be Folio.per_page" do
13
+ was = Folio.per_page
14
+ Folio.per_page = 100
15
+ @object.default_per_page.must_equal 100
16
+ Folio.per_page = was
17
+ end
18
+ end
19
+
20
+ describe "per_page" do
21
+ it "should return default_per_page if nil" do
22
+ @klass.send(:define_method, :default_per_page) { 100 }
23
+ @object.per_page = nil
24
+ @object.per_page.must_equal 100
25
+ end
26
+
27
+ it "should return set value if non-nil" do
28
+ @object.per_page = 100
29
+ @object.per_page.must_equal 100
30
+ end
31
+
32
+ it "should allow setting through argument" do
33
+ @object.per_page(100)
34
+ @object.per_page.must_equal 100
35
+ end
36
+
37
+ it "should cast to integer when setting non-nil through argument" do
38
+ @object.per_page("100")
39
+ @object.per_page.must_equal 100
40
+ end
41
+
42
+ it "should allow setting to nil through argument" do
43
+ @klass.send(:define_method, :default_per_page) { 100 }
44
+ @object.per_page(30)
45
+ @object.per_page(nil)
46
+ @object.per_page.must_equal 100
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,15 @@
1
+ require 'folio/rails'
2
+ require 'folio/invalid_page'
3
+
4
+ describe ActionDispatch::ExceptionWrapper do
5
+ before do
6
+ # stolen from ActionDispatch::Railtie's initializer
7
+ config = ActionDispatch::Railtie.config
8
+ ActionDispatch::ExceptionWrapper.rescue_responses.merge!(config.action_dispatch.rescue_responses)
9
+ end
10
+
11
+ it "should translate Folio::InvalidPage to a 404" do
12
+ wrapper = ActionDispatch::ExceptionWrapper.new({}, Folio::InvalidPage.new)
13
+ wrapper.status_code.must_equal 404
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ require 'minitest/autorun'
2
+ require 'folio/version'
3
+
4
+ describe Folio::VERSION do
5
+ it "should have a version" do
6
+ Folio::VERSION.wont_be_nil
7
+ end
8
+ end
@@ -0,0 +1,118 @@
1
+ require 'minitest/autorun'
2
+ require 'folio/will_paginate/active_record'
3
+ require_relative '../../setup/active_record'
4
+
5
+ describe ActiveRecord do
6
+ TestSetup::ActiveRecord.migrate do |m|
7
+ m.create_table(:items) do |t|
8
+ t.boolean :filter
9
+ end
10
+
11
+ m.create_table(:related_things) do |t|
12
+ t.integer :item_id
13
+ end
14
+ end
15
+
16
+ class Item < ::ActiveRecord::Base
17
+ has_many :related_things
18
+ end
19
+
20
+ class RelatedThing < ::ActiveRecord::Base; end
21
+
22
+ before do
23
+ RelatedThing.delete_all
24
+ Item.delete_all
25
+ 24.times{ |i| Item.create(filter: (i % 2).zero?) }
26
+ end
27
+
28
+ describe "per_page" do
29
+ it "should default to Folio.per_page" do
30
+ was = Folio.per_page
31
+ Folio.per_page = 10
32
+ ActiveRecord::Base.per_page.must_equal 10
33
+ Folio.per_page = was
34
+ end
35
+ end
36
+
37
+ describe "paginate" do
38
+ it "should return an ordinal folio page" do
39
+ page = Item.paginate
40
+ page.is_a?(Folio::Ordinal::Page).must_equal true
41
+ end
42
+
43
+ it "should still return a relation" do
44
+ page = Item.paginate
45
+ page.is_a?(ActiveRecord::Relation).must_equal true
46
+ end
47
+
48
+ it "should set limit_value according to per_page" do
49
+ page = Item.paginate(per_page: 10)
50
+ page.limit_value.must_equal 10
51
+ end
52
+
53
+ it "should use that limit_value as per_page attribute" do
54
+ page = Item.paginate(per_page: 10)
55
+ page.per_page.must_equal 10
56
+ end
57
+
58
+ it "should default limit_value/per_page to model's per_page" do
59
+ was = Item.per_page
60
+ Item.per_page = 10
61
+ page = Item.paginate
62
+ page.limit_value.must_equal 10
63
+ page.per_page.must_equal 10
64
+ Item.per_page = was
65
+ end
66
+
67
+ it "should set offset from page and per_page" do
68
+ page = Item.paginate(page: 3, per_page: 10)
69
+ page.offset_value.must_equal 20
70
+ end
71
+
72
+ it "should set current_page" do
73
+ page = Item.paginate(page: 3, per_page: 10)
74
+ page.current_page.must_equal 3
75
+ end
76
+
77
+ it "should have the right count on the unloaded page" do
78
+ page = Item.paginate(page: 3, per_page: 10)
79
+ page.count.must_equal 4
80
+ end
81
+
82
+ it "should have the right size on the unloaded page" do
83
+ page = Item.paginate(page: 3, per_page: 10)
84
+ page.size.must_equal 4
85
+ end
86
+
87
+ it "should return the expected items" do
88
+ page = Item.paginate(page: 3, per_page: 10)
89
+ page.to_a.must_equal Item.offset(20).all
90
+ end
91
+
92
+ it "should auto-count total_entries unless specified as nil" do
93
+ page = Item.paginate
94
+ page.total_entries.must_equal 24
95
+ end
96
+
97
+ it "should work with total_entries nil" do
98
+ page = Item.paginate(page: 3, total_entries: nil)
99
+ page.current_page.must_equal 3
100
+ end
101
+
102
+ it "should validate page number against auto-counted total_entries" do
103
+ lambda{ Item.paginate(page: 4, per_page: 10) }.must_raise Folio::InvalidPage
104
+ end
105
+
106
+ it "should work on relations" do
107
+ page = Item.where(filter: true).paginate(page: 2, per_page: 10)
108
+ page.count.must_equal 2
109
+ end
110
+
111
+ it "should work on associations" do
112
+ item = Item.first
113
+ 12.times{ |i| item.related_things.create! }
114
+ page = item.related_things.paginate(page: 2, per_page: 10)
115
+ page.count.must_equal 2
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,43 @@
1
+ require 'minitest/autorun'
2
+ require 'folio/will_paginate/collection'
3
+
4
+ describe WillPaginate::Collection do
5
+ describe "create" do
6
+ it "should create an ordinal page" do
7
+ page = WillPaginate::Collection.create(1)
8
+ page.is_a?(Folio::Ordinal::Page).must_equal true
9
+ end
10
+
11
+ it "should set current_page on the created page" do
12
+ page = WillPaginate::Collection.create(4)
13
+ page.current_page.must_equal 4
14
+ end
15
+
16
+ it "should set per_page on the created page if given" do
17
+ page = WillPaginate::Collection.create(4, 10)
18
+ page.per_page.must_equal 10
19
+ end
20
+
21
+ it "should set total_entries on the created page if given" do
22
+ page = WillPaginate::Collection.create(4, 10, 50)
23
+ page.total_entries.must_equal 50
24
+ end
25
+
26
+ it "should yield the page to block if given" do
27
+ page = WillPaginate::Collection.create(1) { |p| p.replace [1, 2, 3] }
28
+ page.must_equal [1, 2, 3]
29
+ end
30
+
31
+ it "created page should have offset method like WillPaginate::Collection" do
32
+ page = WillPaginate::Collection.create(4, 10)
33
+ page.offset.must_equal 30
34
+ end
35
+
36
+ it "created should set total_entries on replace like WillPaginate::Collection" do
37
+ page = WillPaginate::Collection.create(4, 10)
38
+ page.total_entries.must_be_nil
39
+ page.replace [1, 2, 3]
40
+ page.total_entries.must_equal 33
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,58 @@
1
+ require 'minitest/autorun'
2
+ require 'folio/will_paginate/view_helpers/link_renderer_base'
3
+ require 'folio/page'
4
+
5
+ describe WillPaginate::ViewHelpers::LinkRendererBase do
6
+ before do
7
+ @renderer = WillPaginate::ViewHelpers::LinkRendererBase.new
8
+
9
+ # looks just like a standard WillPaginate collection would
10
+ @collection = Folio::Page.create
11
+ @collection.ordinal_pages = true
12
+ @collection.first_page = 1
13
+ @collection.total_entries = 200
14
+ @collection.per_page = 10
15
+ @collection.last_page = 20
16
+ @collection.current_page = 10
17
+ @collection.next_page = 11
18
+ @collection.previous_page = 9
19
+ end
20
+
21
+ it "should ignore page_links parameter with non-ordinal pages" do
22
+ @collection.ordinal_pages = false
23
+ @renderer.prepare(@collection, page_links: true)
24
+ @renderer.pagination.must_equal [:previous_page, :next_page]
25
+ end
26
+
27
+ it "should still honor page_links parameter with ordinal pages" do
28
+ @renderer.prepare(@collection, page_links: false)
29
+ @renderer.pagination.must_equal [:previous_page, :next_page]
30
+
31
+ @renderer.prepare(@collection, page_links: true)
32
+ @renderer.pagination.must_equal [:previous_page, 1, :gap, 10, :gap, 20, :next_page]
33
+ end
34
+
35
+ it "should treat last_page as total_pages when known" do
36
+ @collection.last_page = 15
37
+ @renderer.prepare(@collection, {})
38
+ @renderer.total_pages.must_equal @collection.last_page
39
+ end
40
+
41
+ it "should treat next_page as total_pages when last_page unknown" do
42
+ @collection.last_page = nil
43
+ @renderer.prepare(@collection, {})
44
+ @renderer.total_pages.must_equal @collection.next_page
45
+ end
46
+
47
+ it "should add :gap after page links when last_page unknown" do
48
+ @collection.last_page = nil
49
+ @renderer.prepare(@collection, page_links: true, inner_window: 1)
50
+ @renderer.pagination.must_equal [:previous_page, 1, :gap, 9, 10, 11, :gap, :next_page]
51
+ end
52
+
53
+ it "should end inner window at next_page when last_page unknown" do
54
+ @collection.last_page = nil
55
+ @renderer.prepare(@collection, page_links: true, inner_window: 2)
56
+ @renderer.pagination.must_equal [:previous_page, 1, :gap, 7, 8, 9, 10, 11, :gap, :next_page]
57
+ end
58
+ end
@@ -0,0 +1,58 @@
1
+ require 'minitest/autorun'
2
+ require 'folio/will_paginate/view_helpers/link_renderer'
3
+ require 'folio/page'
4
+
5
+ describe WillPaginate::ViewHelpers::LinkRenderer do
6
+ before do
7
+ klass = Class.new(WillPaginate::ViewHelpers::LinkRenderer) { def url(page); "url://#{page}"; end }
8
+ @renderer = klass.new
9
+ @collection = Folio::Page.create
10
+ end
11
+
12
+ describe "previous_page" do
13
+ it "should respect collection.previous_page" do
14
+ @collection.previous_page = 5
15
+ @renderer.prepare(@collection, {}, nil)
16
+ @renderer.previous_page.must_match %r{url://5}
17
+ end
18
+
19
+ it "should produce link for non-numeric value" do
20
+ @collection.previous_page = "abcdef"
21
+ @renderer.prepare(@collection, {}, nil)
22
+ @renderer.previous_page.must_match %r{url://abcdef}
23
+ end
24
+
25
+ it "should have rel=previous in the html for non-numeric value" do
26
+ @collection.previous_page = "abcdef"
27
+ @renderer.prepare(@collection, {}, nil)
28
+ @renderer.previous_page.must_match %r{rel="prev"}
29
+ end
30
+
31
+ it "should have rel=start in the html for non-numeric value matching first_page" do
32
+ @collection.first_page = "abcdef"
33
+ @collection.previous_page = "abcdef"
34
+ @renderer.prepare(@collection, {}, nil)
35
+ @renderer.previous_page.must_match %r{rel="prev start"}
36
+ end
37
+ end
38
+
39
+ describe "next_page" do
40
+ it "should respect collection.next_page" do
41
+ @collection.next_page = 15
42
+ @renderer.prepare(@collection, {}, nil)
43
+ @renderer.next_page.must_match %r{url://15}
44
+ end
45
+
46
+ it "should produce link for non-numeric value" do
47
+ @collection.next_page = "abcdef"
48
+ @renderer.prepare(@collection, {}, nil)
49
+ @renderer.next_page.must_match %r{url://abcdef}
50
+ end
51
+
52
+ it "should have rel=next in the html for non-numeric value" do
53
+ @collection.next_page = "abcdef"
54
+ @renderer.prepare(@collection, {}, nil)
55
+ @renderer.next_page.must_match %r{rel="next"}
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,49 @@
1
+ require 'minitest/autorun'
2
+ require 'folio/will_paginate/view_helpers'
3
+
4
+ # for I18n in page_entries_info
5
+ require 'active_support/core_ext/string/inflections'
6
+
7
+ describe WillPaginate::ViewHelpers do
8
+ include WillPaginate::ViewHelpers
9
+
10
+ before do
11
+ @collection = Folio::Ordinal::Page.create
12
+ end
13
+
14
+ describe "will_paginate" do
15
+ before do
16
+ @renderer = Minitest::Mock.new
17
+ @renderer.expect(:prepare, nil, [@collection, Hash, self])
18
+ @renderer.expect(:to_html, '<PAGES>')
19
+ end
20
+
21
+ it "should return nil if total_pages is 1" do
22
+ @collection.total_entries = @collection.per_page
23
+ will_paginate(@collection, :renderer => @renderer).must_be_nil
24
+ end
25
+
26
+ it "should not error if total_entries is unknown" do
27
+ @collection.total_entries = nil
28
+ will_paginate(@collection, :renderer => @renderer).must_equal '<PAGES>'
29
+ end
30
+ end
31
+
32
+ describe "page_entries_info" do
33
+ it "should return nominally if collection is ordinal with total_entries known" do
34
+ @collection.total_entries = 20
35
+ page_entries_info(@collection).wont_be_nil
36
+ end
37
+
38
+ it "should return nil if total_entries is unknown" do
39
+ @collection.total_entries = nil
40
+ page_entries_info(@collection).must_be_nil
41
+ end
42
+
43
+ it "should return nil if collection is non-ordinal" do
44
+ @collection = Folio::Page.create
45
+ @collection.total_entries = 20
46
+ page_entries_info(@collection).must_be_nil
47
+ end
48
+ end
49
+ end