folio-pagination 0.0.2

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.
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