diff --git a/apps/pagy_calendar_app.ru b/apps/pagy_calendar_app.ru index e98420f1f..bfe48d5c1 100644 --- a/apps/pagy_calendar_app.ru +++ b/apps/pagy_calendar_app.ru @@ -112,7 +112,8 @@ __END__ <% else %> Hide Calendar
- Go to current Page + Go to the 2022-03 Page + <% end %>

diff --git a/lib/pagy/calendar.rb b/lib/pagy/calendar.rb index 35c7c837f..236f53fed 100644 --- a/lib/pagy/calendar.rb +++ b/lib/pagy/calendar.rb @@ -12,9 +12,6 @@ class Pagy # :nodoc: # Base class for time units subclasses (Year, Quarter, Month, Week, Day) class Calendar < Pagy - # Specific out of range error - class OutOfRangeError < StandardError; end - # List of units in desc order of duration. It can be used for custom units. UNITS = %i[year quarter month week day] # rubocop:disable Style/MutableConstant @@ -49,10 +46,21 @@ def label_for(page, opts = {}) protected # The page that includes time + # Return the first page when the time requested is before the initial time + # Return the last page when the time requested is after the final time def page_at(time) - raise OutOfRangeError unless time.between?(@initial, @final) - - offset = page_offset_at(time) # offset starts from 0 + adjusted_time = time + unless time.between?(@initial, @final) + if time < @initial && time < @final + adjusted_time = @initial + ordinal = 'first' + elsif time > @initial && time > @final + adjusted_time = @final - 1 + ordinal = 'last' + end + Warning.warn "Pagy::Calendar#page_at: Requested time out of range. Returning the #{ordinal} page." + end + offset = page_offset_at(adjusted_time) # offset starts from 0 @order == :asc ? offset + 1 : @pages - offset end diff --git a/test/coverage_setup.rb b/test/coverage_setup.rb index 7f9131cc8..dc3453758 100644 --- a/test/coverage_setup.rb +++ b/test/coverage_setup.rb @@ -12,6 +12,7 @@ command_name "Task##{$PROCESS_ID}" merge_timeout 20 enable_coverage :branch + add_filter "/test/" add_group 'Core', %w[ lib/pagy.rb lib/pagy/backend.rb lib/pagy/console.rb @@ -21,7 +22,7 @@ lib/pagy/i18n.rb lib/pagy/url_helpers.rb ] add_group 'Extras', 'lib/pagy/extras' - add_group 'Tests', 'test' + # add_group 'Tests', 'test' end SimpleCov.formatter = SimpleCov::Formatter::SimpleFormatter unless ENV.fetch('HTML_REPORTS', nil) == 'true' diff --git a/test/pagy/calendar_test.rb b/test/pagy/calendar_test.rb index 066cc3176..a4a638192 100644 --- a/test/pagy/calendar_test.rb +++ b/test/pagy/calendar_test.rb @@ -277,14 +277,16 @@ def pagy(unit: :month, **vars) _(p.send(:page_at, Time.zone.local(2021, 10, 21, 13, 18, 23, 0))).must_equal 1 _(p.send(:page_at, Time.zone.local(2022, 1, 1, 13, 18, 23, 0))).must_equal 2 _(p.send(:page_at, Time.zone.local(2023, 11, 13, 15, 43, 40, 0))).must_equal 3 - _ { p.send(:page_at, Time.zone.local(2030)) }.must_raise Pagy::Calendar::OutOfRangeError + _(p.send(:page_at, Time.zone.local(2100))).must_equal 3 + _(p.send(:page_at, Time.zone.local(2000))).must_equal 1 end it 'returns the page number for :year desc' do p = pagy(unit: :year, order: :desc) _(p.send(:page_at, Time.zone.local(2021, 10, 21, 13, 18, 23, 0))).must_equal 3 _(p.send(:page_at, Time.zone.local(2022, 1, 1, 13, 18, 23, 0))).must_equal 2 _(p.send(:page_at, Time.zone.local(2023, 11, 13, 15, 43, 40, 0))).must_equal 1 - _ { p.send(:page_at, Time.zone.local(2030)) }.must_raise Pagy::Calendar::OutOfRangeError + _(p.send(:page_at, Time.zone.local(2100))).must_equal 1 + _(p.send(:page_at, Time.zone.local(2000))).must_equal 3 end it 'returns the page number for :quarter' do @@ -292,28 +294,32 @@ def pagy(unit: :month, **vars) _(p.send(:page_at, Time.zone.local(2021, 10, 21, 13, 18, 23, 0))).must_equal 1 _(p.send(:page_at, Time.zone.local(2022, 1, 1, 13, 18, 23, 0))).must_equal 2 _(p.send(:page_at, Time.zone.local(2023, 11, 13, 15, 43, 40, 0))).must_equal 9 - _ { p.send(:page_at, Time.zone.local(2030)) }.must_raise Pagy::Calendar::OutOfRangeError + _(p.send(:page_at, Time.zone.local(2100))).must_equal 9 + _(p.send(:page_at, Time.zone.local(2000))).must_equal 1 end it 'returns the page number for :quarter desc' do p = pagy(unit: :quarter, order: :desc) _(p.send(:page_at, Time.zone.local(2021, 10, 21, 13, 18, 23, 0))).must_equal 9 _(p.send(:page_at, Time.zone.local(2022, 1, 1, 13, 18, 23, 0))).must_equal 8 _(p.send(:page_at, Time.zone.local(2023, 11, 13, 15, 43, 40, 0))).must_equal 1 - _ { p.send(:page_at, Time.zone.local(2030)) }.must_raise Pagy::Calendar::OutOfRangeError + _(p.send(:page_at, Time.zone.local(2100))).must_equal 1 + _(p.send(:page_at, Time.zone.local(2000))).must_equal 9 end it 'returns the page number for :month' do p = pagy(unit: :month) _(p.send(:page_at, Time.zone.local(2021, 10, 21, 13, 18, 23, 0))).must_equal 1 _(p.send(:page_at, Time.zone.local(2022, 1, 1, 13, 18, 23, 0))).must_equal 4 _(p.send(:page_at, Time.zone.local(2023, 11, 13, 15, 43, 40, 0))).must_equal 26 - _ { p.send(:page_at, Time.zone.local(2030)) }.must_raise Pagy::Calendar::OutOfRangeError + _(p.send(:page_at, Time.zone.local(2100))).must_equal 26 + _(p.send(:page_at, Time.zone.local(2000))).must_equal 1 end it 'returns the page number for :month desc' do p = pagy(unit: :month, order: :desc) _(p.send(:page_at, Time.zone.local(2021, 10, 21, 13, 18, 23, 0))).must_equal 26 _(p.send(:page_at, Time.zone.local(2022, 1, 1, 13, 18, 23, 0))).must_equal 23 _(p.send(:page_at, Time.zone.local(2023, 11, 13, 15, 43, 40, 0))).must_equal 1 - _ { p.send(:page_at, Time.zone.local(2030)) }.must_raise Pagy::Calendar::OutOfRangeError + _(p.send(:page_at, Time.zone.local(2100))).must_equal 1 + _(p.send(:page_at, Time.zone.local(2000))).must_equal 26 end it 'returns the page number for :week' do @@ -321,28 +327,32 @@ def pagy(unit: :month, **vars) _(p.send(:page_at, Time.zone.local(2021, 10, 21))).must_equal 1 _(p.send(:page_at, Time.zone.local(2021, 10, 26))).must_equal 2 _(p.send(:page_at, Time.zone.local(2023, 11, 13))).must_equal 109 - _ { p.send(:page_at, Time.zone.local(2030)) }.must_raise Pagy::Calendar::OutOfRangeError + _(p.send(:page_at, Time.zone.local(2100))).must_equal 109 + _(p.send(:page_at, Time.zone.local(2000))).must_equal 1 end - it 'returns the page number for :day desc' do + it 'returns the page number for :week desc' do p = pagy(unit: :week, order: :desc) _(p.send(:page_at, Time.zone.local(2021, 10, 21))).must_equal 109 _(p.send(:page_at, Time.zone.local(2021, 10, 26))).must_equal 108 _(p.send(:page_at, Time.zone.local(2023, 11, 13))).must_equal 1 - _ { p.send(:page_at, Time.zone.local(2030)) }.must_raise Pagy::Calendar::OutOfRangeError + _(p.send(:page_at, Time.zone.local(2100))).must_equal 1 + _(p.send(:page_at, Time.zone.local(2000))).must_equal 109 end it 'returns the page number for :day' do p = pagy(unit: :day) _(p.send(:page_at, Time.zone.local(2021, 10, 21))).must_equal 1 _(p.send(:page_at, Time.zone.local(2021, 10, 26))).must_equal 6 _(p.send(:page_at, Time.zone.local(2023, 11, 13))).must_equal 754 - _ { p.send(:page_at, Time.zone.local(2030)) }.must_raise Pagy::Calendar::OutOfRangeError + _(p.send(:page_at, Time.zone.local(2100))).must_equal 754 + _(p.send(:page_at, Time.zone.local(2000))).must_equal 1 end it 'returns the page number for :day desc' do p = pagy(unit: :day, order: :desc) _(p.send(:page_at, Time.zone.local(2021, 10, 21))).must_equal 754 _(p.send(:page_at, Time.zone.local(2021, 10, 26))).must_equal 749 _(p.send(:page_at, Time.zone.local(2023, 11, 13))).must_equal 1 - _ { p.send(:page_at, Time.zone.local(2030)) }.must_raise Pagy::Calendar::OutOfRangeError + _(p.send(:page_at, Time.zone.local(2100))).must_equal 1 + _(p.send(:page_at, Time.zone.local(2000))).must_equal 754 end end diff --git a/test/pagy/extras/calendar_extra_test.rb b/test/pagy/extras/calendar_extra_test.rb index 6aa9bdf06..8200c60b6 100644 --- a/test/pagy/extras/calendar_extra_test.rb +++ b/test/pagy/extras/calendar_extra_test.rb @@ -228,11 +228,11 @@ def app(**opts) _(app.send(:pagy_calendar_url_at, calendar, Time.zone.local(2023, 11, 10))) .must_equal "/foo?page=1&year_page=3&month_page=11" - _ { app.send(:pagy_calendar_url_at, calendar, Time.zone.local(2024, 1, 10)) } - .must_raise Pagy::Calendar::OutOfRangeError + _(app.send(:pagy_calendar_url_at, calendar, Time.zone.local(2100))) + .must_equal "/foo?page=1&year_page=3&month_page=11" - _ { app.send(:pagy_calendar_url_at, calendar, Time.zone.local(2021, 9, 10)) } - .must_raise Pagy::Calendar::OutOfRangeError + _(app.send(:pagy_calendar_url_at, calendar, Time.zone.local(2000))) + .must_equal "/foo?page=1&year_page=1&month_page=1" end end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 23e44e79f..7767bf031 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -15,3 +15,14 @@ $LOAD_PATH.unshift File.expand_path('../lib', __dir__) require 'pagy' require 'minitest/autorun' + +module PagyCalendarWarningFilter + def warn(message, category: nil, **kwargs) + if 'Calendar#page_at'.match?(message) + # ignore + else + super + end + end +end +Warning.extend PagyCalendarWarningFilter