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,132 @@
1
+ begin
2
+ require 'will_paginate/active_record'
3
+ rescue LoadError
4
+ raise "folio-pagination's activerecord support requires will_paginate"
5
+ end
6
+
7
+ require 'folio/page'
8
+ require 'folio/ordinal'
9
+ require 'folio/ordinal/page'
10
+
11
+ module Folio
12
+ module WillPaginate
13
+ # enhances model_or_scope.page(n) method from WillPaginate to behave like a
14
+ # Folio::Ordinal::Page. replaces model_or_scope.paginate(...) method to
15
+ # behave like that from Folio while preserving basic mechanics of the
16
+ # version from WillPaginate.
17
+ #
18
+ # differences:
19
+ #
20
+ # * total_entries loading via count is *not* deferred as it was under
21
+ # WillPaginate.
22
+ #
23
+ # * paginate does *not* recognize any parameters beyond those described in
24
+ # for Folio's paginate (e.g. finder options, count options).
25
+ #
26
+ module ActiveRecord
27
+ module RelationMethods
28
+ include Folio::Page
29
+ include Folio::Ordinal::Page
30
+
31
+ # overrides Folio::Page's per_page similar to WillPaginate's version,
32
+ # but uses correct semantics for per_page(nil) (vs. per_page()).
33
+ def per_page(*args)
34
+ if args.size > 0
35
+ raise ArgumentError if args.size > 1
36
+ value ||= @klass.per_page
37
+ limit(value)
38
+ end
39
+ limit_value
40
+ end
41
+
42
+ # overrides WillPaginate's weird "ignore limit when counting" behavior.
43
+ # I can't fall back on super in the branch with a limit_value, since
44
+ # that would fall into WillPaginate's lap, but since there is a
45
+ # limit_value, safe enough to just instantiate and check length
46
+ def count
47
+ if limit_value
48
+ to_a.size
49
+ else
50
+ super
51
+ end
52
+ end
53
+ end
54
+
55
+ module Pagination
56
+ # turns the sequence of calls made by Folio::Ordinal#paginate into the
57
+ # construction of an appropriate relation
58
+ class PageProxy
59
+ def initialize(target)
60
+ @target = target
61
+ end
62
+
63
+ # needed to prevent Folio::Ordinal#configure_pagination from trying
64
+ # to decorate it
65
+ include Folio::Ordinal::Page
66
+
67
+ # called during Folio#configure_pagination, used to build up @rel
68
+ # from @target and the arguments
69
+ attr_writer :current_page
70
+
71
+ def per_page=(per_page)
72
+ @rel = @target.limit(per_page.to_i).page(@current_page)
73
+ @rel.limit_value
74
+ end
75
+
76
+ def total_entries=(total_entries)
77
+ @rel.total_entries = total_entries
78
+ end
79
+
80
+ # called during Folio::Ordinal#configure_pagination for bounds
81
+ # checking, before the proxy has been replaced by its result
82
+ def current_page
83
+ @rel.current_page
84
+ end
85
+
86
+ def out_of_bounds?
87
+ @rel.out_of_bounds?
88
+ end
89
+
90
+ # get the result of the construction back out during fill_page
91
+ def result
92
+ @rel
93
+ end
94
+ end
95
+
96
+ # set up the proxy to receive the calls
97
+ def build_page
98
+ PageProxy.new(self)
99
+ end
100
+
101
+ # pull the result out of the proxy
102
+ def fill_page(proxy)
103
+ proxy.result
104
+ end
105
+
106
+ # make sure the relation coming out of page(...) is folio-compatible
107
+ def page(num)
108
+ super.extending(RelationMethods)
109
+ end
110
+
111
+ # don't try and look at Class (ActiveRecord::Base.class, etc.) for
112
+ # defaults
113
+ def default_per_page
114
+ Folio.per_page
115
+ end
116
+
117
+ include ::Folio::Ordinal
118
+ end
119
+
120
+ # mix into Active Record. these are the same ones that WillPaginate mixes
121
+ # its version of Pagination into.
122
+ ::ActiveRecord::Base.extend Pagination
123
+ klasses = [::ActiveRecord::Relation]
124
+ if defined? ::ActiveRecord::Associations::CollectionProxy
125
+ klasses << ::ActiveRecord::Associations::CollectionProxy
126
+ else
127
+ klasses << ::ActiveRecord::Associations::AssociationCollection
128
+ end
129
+ klasses.each { |klass| klass.send(:include, Pagination) }
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,19 @@
1
+ require 'folio'
2
+ require 'folio/ordinal/page'
3
+ require 'will_paginate/collection'
4
+
5
+ # overrides WillPaginate::Collection.create to return an ordinal folio page
6
+ # instead of a WillPaginate::Collection; the rest of WillPaginate::Collection
7
+ # is unused when in folio-land.
8
+ module WillPaginate
9
+ class Collection
10
+ def self.create(current_page, per_page=nil, total_entries=nil)
11
+ page = ::Folio::Ordinal::Page.create
12
+ page.current_page = current_page
13
+ page.per_page = per_page
14
+ page.total_entries = total_entries
15
+ yield page if block_given?
16
+ page
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,10 @@
1
+ begin
2
+ require 'will_paginate/view_helpers/action_view'
3
+ rescue LoadError
4
+ raise "folio-pagination's actionview support requires will_paginate"
5
+ end
6
+
7
+ require 'folio/will_paginate/view_helpers'
8
+
9
+ # no overrides specific to action view necessary. just including the general
10
+ # view_helper overrides as above is sufficient.
@@ -0,0 +1,54 @@
1
+ require 'will_paginate/view_helpers/link_renderer'
2
+
3
+ module Folio
4
+ module WillPaginate
5
+ module ViewHelpers
6
+ module LinkRenderer
7
+ def previous_page_with_folio
8
+ # the page identifier may not be ordinal; use the value as set on the
9
+ # collection, instead.
10
+ previous_or_next_page(@collection.previous_page, @options[:previous_label], 'previous_page')
11
+ end
12
+
13
+ def next_page_with_folio
14
+ # the page identifier may not be ordinal; use the value as set on the
15
+ # collection, instead.
16
+ previous_or_next_page(@collection.next_page, @options[:next_label], 'next_page')
17
+ end
18
+
19
+ def link_with_folio(text, target, attributes = {})
20
+ if target
21
+ # the non-folio version only does this for Fixnums, but we want to
22
+ # do it for any page value. fortunately, this method only ever
23
+ # receives Fixnums or nil, so we can do it now for any non-nil
24
+ # value, and the non-folio version will happily avoid a double
25
+ # application because even when the page was a fixnum, it won't be
26
+ # anymore.
27
+ attributes[:rel] = rel_value(target)
28
+ target = url(target)
29
+ end
30
+ link_without_folio(text, target, attributes)
31
+ end
32
+
33
+ def rel_value_with_folio(page)
34
+ # don't check against mathed out values, just check the values on the
35
+ # collection
36
+ rels = []
37
+ rels << 'prev' if page == @collection.previous_page
38
+ rels << 'next' if page == @collection.next_page
39
+ rels << 'start' if page == @collection.first_page
40
+ rels.empty? ? nil : rels.join(' ')
41
+ end
42
+
43
+ def self.included(klass)
44
+ [:previous_page, :next_page, :link, :rel_value].each do |method|
45
+ klass.send(:alias_method, :"#{method}_without_folio", method)
46
+ klass.send(:alias_method, method, :"#{method}_with_folio")
47
+ end
48
+ end
49
+
50
+ ::WillPaginate::ViewHelpers::LinkRenderer.send :include, self
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,44 @@
1
+ require 'will_paginate/view_helpers/link_renderer_base'
2
+
3
+ module Folio
4
+ module WillPaginate
5
+ module ViewHelpers
6
+ module LinkRendererBase
7
+ def prepare_with_folio(collection, options)
8
+ # only include page_links if we're in a collection with ordinal
9
+ # pages; otherwise stick to just prev/next.
10
+ options = options.merge(page_links: false) unless collection.ordinal_pages?
11
+ prepare_without_folio(collection, options)
12
+ end
13
+
14
+ def windowed_page_numbers_with_folio
15
+ page_numbers = windowed_page_numbers_without_folio
16
+ unless @collection.last_page
17
+ # the last page is not known, so add a trailing gap (it won't
18
+ # already be there, because the right range during the super call
19
+ # won't exist).
20
+ page_numbers << :gap
21
+ end
22
+ page_numbers
23
+ end
24
+
25
+ def total_pages_with_folio
26
+ # the collection may not have a known last page. if so, there must be
27
+ # a next page; count that as the last known page. it's ok to use
28
+ # these page identifiers as a page count because (after fixing
29
+ # LinkRenderer) it's only called when ordinal_pages is true.
30
+ @collection.last_page || @collection.next_page
31
+ end
32
+
33
+ def self.included(klass)
34
+ [:prepare, :windowed_page_numbers, :total_pages].each do |method|
35
+ klass.send(:alias_method, :"#{method}_without_folio", method)
36
+ klass.send(:alias_method, method, :"#{method}_with_folio")
37
+ end
38
+ end
39
+
40
+ ::WillPaginate::ViewHelpers::LinkRendererBase.send :include, self
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,57 @@
1
+ require 'folio'
2
+ require 'folio/will_paginate/view_helpers/link_renderer_base'
3
+ require 'folio/will_paginate/view_helpers/link_renderer'
4
+ require 'will_paginate/view_helpers'
5
+
6
+ module Folio
7
+ module WillPaginate
8
+ module ViewHelpers
9
+ # just copied from ::WillPaginate::ViewHelpers except line 14 (changed from
10
+ # "unless value > 1" to "if value == 1" to be friendly to unknown
11
+ # total_pages)
12
+ def will_paginate_with_folio(collection, options = {})
13
+ # early exit if there is nothing to render
14
+ return nil if collection.total_pages == 1
15
+
16
+ options = ::WillPaginate::ViewHelpers.pagination_options.merge(options)
17
+
18
+ options[:previous_label] ||= will_paginate_translate(:previous_label) { '&#8592; Previous' }
19
+ options[:next_label] ||= will_paginate_translate(:next_label) { 'Next &#8594;' }
20
+
21
+ # get the renderer instance
22
+ renderer = case options[:renderer]
23
+ when nil
24
+ raise ArgumentError, ":renderer not specified"
25
+ when String
26
+ klass = if options[:renderer].respond_to? :constantize then options[:renderer].constantize
27
+ else Object.const_get(options[:renderer]) # poor man's constantize
28
+ end
29
+ klass.new
30
+ when Class then options[:renderer].new
31
+ else options[:renderer]
32
+ end
33
+ # render HTML for pagination
34
+ renderer.prepare collection, options, self
35
+ output = renderer.to_html
36
+ output = output.html_safe if output.respond_to?(:html_safe)
37
+ output
38
+ end
39
+
40
+ def page_entries_info_with_folio(collection, options = {})
41
+ # skip outputting anything unless the collection has ordinal pages (to
42
+ # be able to get an offset) *and* a known total count.
43
+ return unless collection.total_entries && collection.ordinal_pages
44
+ page_entries_info_without_folio(collection, options)
45
+ end
46
+
47
+ def self.included(klass)
48
+ [:will_paginate, :page_entries_info].each do |method|
49
+ klass.send(:alias_method, :"#{method}_without_folio", method)
50
+ klass.send(:alias_method, method, :"#{method}_with_folio")
51
+ end
52
+ end
53
+
54
+ ::WillPaginate::ViewHelpers.send :include, self
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,3 @@
1
+ # convenience so that you can require by the gem name and get the same effect
2
+ # as requiring the canonical 'folio'.
3
+ require 'folio'
data/lib/folio.rb ADDED
@@ -0,0 +1,84 @@
1
+ require "folio/version"
2
+ require "folio/per_page"
3
+
4
+ # Mix into any class implementing the following two methods:
5
+ #
6
+ # +build_page+: Responsible for instantiating a Folio::Page and
7
+ # configuring its ordinal_pages?, first_page, and last_page attributes;
8
+ # those values being common to any page returned from the folio.
9
+ #
10
+ # +fill_page+: Receives a Folio::Page with the ordinal_pages?,
11
+ # first_page, last_page, current_page, per_page, and total_entries
12
+ # attributes configured, and populates the page with the corresponding
13
+ # items from the folio. Also sets appropriate values for the next_page
14
+ # and previous_page attributes on the page. If the value provided in the
15
+ # page's current_page cannot be interpreted as addressing a page in the
16
+ # folio, raises Folio::InvalidPage.
17
+ #
18
+ # In return, `Folio` provides a the paginate method and per_page
19
+ # attributes described below.
20
+ module Folio
21
+ # Returns a page worth of items from the folio in a Folio::Page.
22
+ # accepts the following parameters:
23
+ #
24
+ # +page+: a page identifier addressing which page of the folio to
25
+ # return. if not present, the first page will be returned. will raise
26
+ # Folio::InvalidPage if the provided value cannot be used to address a
27
+ # page.
28
+ #
29
+ # +per_page+: number of items to attempt to include in the page. if
30
+ # not present, defaults to the folio's per_page value. should only
31
+ # include fewer items if the end of the folio is reached.
32
+ #
33
+ # +total_entries+: pre-calculated value for the total number of items
34
+ # in the folio. may be nil, indicating the returned page should have
35
+ # total_entries nil.
36
+ #
37
+ # if the folio implements a count method and the total_entries
38
+ # parameter is not supplied, the page's total_entries will be set from
39
+ # the count method.
40
+ def paginate(options={})
41
+ page = self.build_page
42
+ page = self.configure_pagination(page, options)
43
+ page = self.fill_page(page)
44
+ page
45
+ end
46
+
47
+ def configure_pagination(page, options)
48
+ current_page = options.fetch(:page) { nil }
49
+ current_page = page.first_page if current_page.nil?
50
+ page.current_page = current_page
51
+ page.per_page = options.fetch(:per_page) { self.per_page }
52
+ page.total_entries = options.fetch(:total_entries) { self.respond_to?(:count) ? self.count : nil }
53
+ page
54
+ end
55
+
56
+ def default_per_page
57
+ self.class.per_page
58
+ end
59
+
60
+ include ::Folio::PerPage
61
+
62
+ # this funny pattern is so that if a module (e.g. Folio::Ordinal)
63
+ # includes this module, it won't get the per_page attribute, but will
64
+ # still be able to bestow that attribute on any class that includes
65
+ # *it*.
66
+ module PerPageIncluder
67
+ def included(klass)
68
+ if klass.is_a?(Class)
69
+ klass.extend ::Folio::PerPage
70
+ else
71
+ klass.extend ::Folio::PerPageIncluder
72
+ end
73
+ end
74
+ end
75
+
76
+ extend PerPageIncluder
77
+ extend PerPage
78
+ per_page(30)
79
+ end
80
+
81
+ # load the other commonly used portions of the gem
82
+ require "folio/page"
83
+ require "folio/ordinal"
84
+ require "folio/ordinal/page"
@@ -0,0 +1,55 @@
1
+ require 'minitest/autorun'
2
+ require 'folio/core_ext/enumerable'
3
+
4
+ describe Array do
5
+ it "should be an ordinal folio" do
6
+ assert_respond_to [], :build_page
7
+ [].build_page.first_page.must_equal 1
8
+ end
9
+
10
+ describe "per_page" do
11
+ it "should have per_page attribute as expected on instances" do
12
+ assert_respond_to [], :per_page
13
+ assert_respond_to [], :per_page=
14
+ end
15
+
16
+ it "should not have per_page attribute on classes" do
17
+ Array.wont_respond_to :per_page
18
+ Array.wont_respond_to :per_page=
19
+ end
20
+
21
+ it "should default to Folio.per_page" do
22
+ was = Folio.per_page
23
+ Folio.per_page = 100
24
+ [].per_page.must_equal 100
25
+ Folio.per_page = was
26
+ end
27
+ end
28
+
29
+ describe "paginate" do
30
+ before do
31
+ @ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
32
+ end
33
+
34
+ it "should return a page" do
35
+ page = @ary.paginate
36
+ assert_respond_to page, :current_page
37
+ end
38
+
39
+ it "should return appropriate slice" do
40
+ @ary.paginate(page: 2, per_page: 4).must_equal [5, 6, 7, 8]
41
+ end
42
+
43
+ it "should return partial slice at end" do
44
+ @ary.paginate(page: 3, per_page: 4).must_equal [9, 10]
45
+ end
46
+
47
+ it "should raise InvalidPage after end even if size unknown" do
48
+ lambda{ @ary.paginate(page: 3, per_page: 5, total_entries: nil) }.must_raise Folio::InvalidPage
49
+ end
50
+
51
+ it "should return empty first page if empty" do
52
+ [].paginate.must_equal []
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,173 @@
1
+ require 'minitest/autorun'
2
+ require 'folio/ordinal'
3
+
4
+ describe Folio::Ordinal::Page do
5
+ before do
6
+ @page = Folio::Ordinal::Page.create
7
+ @page.current_page = 1
8
+ @page.per_page = 10
9
+ @page.total_entries = 30
10
+ end
11
+
12
+ it "should have ordinal_pages=true" do
13
+ @page.ordinal_pages.must_equal true
14
+ @page.ordinal_pages?.must_equal true
15
+ end
16
+
17
+ it "should have first_page=1" do
18
+ @page.first_page.must_equal 1
19
+ end
20
+
21
+ it "should force current_page to an integer" do
22
+ @page.current_page = "3"
23
+ @page.current_page.must_equal 3
24
+ end
25
+
26
+ describe "when total pages known" do
27
+ it "should have last_page=total_pages" do
28
+ @page.last_page.must_equal @page.total_pages
29
+
30
+ @page.total_entries = 0
31
+ @page.last_page.must_equal @page.total_pages
32
+
33
+ @page.total_entries = nil
34
+ @page.last_page.must_equal @page.total_pages
35
+ end
36
+
37
+ it "should have next_page=current_page+1 when not at end" do
38
+ @page.current_page = 2
39
+ @page.next_page.must_equal 3
40
+ end
41
+
42
+ it "should still have next_page=current_page+1 when not at end, despite set value" do
43
+ @page.current_page = 2
44
+ @page.next_page = nil
45
+ @page.next_page.must_equal 3
46
+ end
47
+
48
+ it "should have next_page=nil when at end" do
49
+ @page.current_page = 3
50
+ @page.next_page.must_be_nil
51
+ end
52
+
53
+ it "should still have next_page=nil when at end, despite set value" do
54
+ @page.current_page = 3
55
+ @page.next_page = 4
56
+ @page.next_page.must_be_nil
57
+ end
58
+ end
59
+
60
+ describe "when total pages not known" do
61
+ before do
62
+ @page.total_entries = nil
63
+ end
64
+
65
+ it "should have last_page=nil if next_page is known or assumed" do
66
+ # @page.next_page unset
67
+ @page.last_page.must_be_nil
68
+
69
+ # @page.next_page explicitly non-nil
70
+ @page.next_page = 2
71
+ @page.last_page.must_be_nil
72
+ end
73
+
74
+ it "should have last_page=current_page if next_page is explicitly nil" do
75
+ @page.next_page = nil
76
+ @page.last_page.must_equal @page.current_page
77
+ end
78
+
79
+ it "should have next_page=current_page+1 when not explicitly set" do
80
+ @page.current_page = 2
81
+ @page.next_page.must_equal 3
82
+ end
83
+
84
+ it "should force non-nil set next_page to an integer" do
85
+ @page.next_page = "4"
86
+ @page.next_page.must_equal 4
87
+ end
88
+
89
+ it "should not force nil set next_page to an integer" do
90
+ @page.next_page = nil
91
+ @page.next_page.must_be_nil
92
+ end
93
+
94
+ it "should have next_page=set value when explicitly set" do
95
+ @page.next_page = nil
96
+ @page.current_page = 2
97
+ @page.next_page.must_be_nil
98
+ end
99
+ end
100
+
101
+ it "should have previous_page=nil when at beginning" do
102
+ @page.current_page = 1
103
+ @page.previous_page.must_be_nil
104
+ end
105
+
106
+ it "should have previous_page=current_page-1 when not at beginning" do
107
+ @page.current_page = 3
108
+ @page.previous_page.must_equal 2
109
+ end
110
+
111
+ describe "out_of_bounds?" do
112
+ it "should be false if in first_page..last_page range" do
113
+ @page.current_page = 1
114
+ @page.out_of_bounds?.must_equal false
115
+
116
+ @page.current_page = 3
117
+ @page.out_of_bounds?.must_equal false
118
+ end
119
+
120
+ it "should be true if negative page" do
121
+ @page.current_page = -1
122
+ @page.out_of_bounds?.must_equal true
123
+ end
124
+
125
+ it "should be true if zero page" do
126
+ @page.current_page = 0
127
+ @page.out_of_bounds?.must_equal true
128
+ end
129
+
130
+ it "should be true after known last_page" do
131
+ @page.current_page = 4
132
+ @page.out_of_bounds?.must_equal true
133
+ end
134
+
135
+ it "should not care about large numbers when total_pages not known" do
136
+ @page.total_entries = nil
137
+ @page.current_page = 50
138
+ @page.out_of_bounds?.must_equal false
139
+ end
140
+ end
141
+
142
+ describe "decorate" do
143
+ before do
144
+ @page = Folio::Ordinal::Page.decorate([])
145
+ end
146
+
147
+ it "should add page methods to the object" do
148
+ assert_respond_to @page, :current_page
149
+ end
150
+
151
+ it "should add ordinal page methods to the object" do
152
+ @page.first_page.must_equal 1
153
+ end
154
+
155
+ it "should preserve other methods on the object" do
156
+ assert_respond_to @page, :each
157
+ end
158
+ end
159
+
160
+ describe "create" do
161
+ before do
162
+ @page = Folio::Ordinal::Page.create
163
+ end
164
+
165
+ it "should be an Array at heart" do
166
+ @page.must_be :is_a?, Array
167
+ end
168
+
169
+ it "should be decorated as an ordinal page" do
170
+ @page.first_page.must_equal 1
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,57 @@
1
+ require 'minitest/autorun'
2
+ require 'folio/ordinal'
3
+
4
+ describe Folio::Ordinal do
5
+ before do
6
+ klass = Class.new do
7
+ def build_page
8
+ Folio::Page.create
9
+ end
10
+
11
+ def fill_page(page)
12
+ page
13
+ end
14
+
15
+ include Folio::Ordinal
16
+ end
17
+ @folio = klass.new
18
+ end
19
+
20
+ describe "paginate" do
21
+ it "should decorate the result of build_page" do
22
+ @page = @folio.paginate
23
+ @page.is_a?(Folio::Ordinal::Page).must_equal true
24
+ end
25
+
26
+ describe "bounds checking" do
27
+ before do
28
+ @folio.per_page = 10
29
+ end
30
+
31
+ it "should raise on non-integer page" do
32
+ lambda{ @folio.paginate(page: "non-integer") }.must_raise Folio::InvalidPage
33
+ end
34
+
35
+ it "should raise on negative page" do
36
+ lambda{ @folio.paginate(page: -1) }.must_raise Folio::InvalidPage
37
+ end
38
+
39
+ it "should raise on page of 0" do
40
+ lambda{ @folio.paginate(page: 0) }.must_raise Folio::InvalidPage
41
+ end
42
+
43
+ it "should raise on page greater than known last_page" do
44
+ lambda{ @folio.paginate(page: 4, total_entries: 30) }.must_raise Folio::InvalidPage
45
+ end
46
+
47
+ it "should not raise on page number between first_page and known last_page" do
48
+ @folio.paginate(page: 1, total_entries: 30)
49
+ @folio.paginate(page: 3, total_entries: 30)
50
+ end
51
+
52
+ it "should not raise on large page if last_page unknown" do
53
+ @folio.paginate(page: 100)
54
+ end
55
+ end
56
+ end
57
+ end