berrypod/test/berrypod/pagination_test.exs
jamey 3480b326a9
All checks were successful
deploy / deploy (push) Successful in 1m38s
add pagination across all admin and shop views
URL-based offset pagination with ?page=N for bookmarkable pages.
Admin views use push_patch, shop collection uses navigate links.
Responsive on mobile with horizontal-scroll tables and stacking
pagination controls. Includes dev seed script for testing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 09:42:34 +00:00

156 lines
4.4 KiB
Elixir

defmodule Berrypod.PaginationTest do
use Berrypod.DataCase, async: true
alias Berrypod.Pagination
describe "page_numbers/1" do
test "returns all pages when total <= 7" do
assert Pagination.page_numbers(page(1, 1)) == [1]
assert Pagination.page_numbers(page(1, 5)) == [1, 2, 3, 4, 5]
assert Pagination.page_numbers(page(3, 7)) == [1, 2, 3, 4, 5, 6, 7]
end
test "shows ellipsis for large page counts" do
result = Pagination.page_numbers(page(1, 20))
assert result == [1, 2, :ellipsis, 20]
end
test "shows window around current page" do
result = Pagination.page_numbers(page(10, 20))
assert result == [1, :ellipsis, 9, 10, 11, :ellipsis, 20]
end
test "current page near start" do
result = Pagination.page_numbers(page(2, 20))
assert result == [1, 2, 3, :ellipsis, 20]
end
test "current page near end" do
result = Pagination.page_numbers(page(19, 20))
assert result == [1, :ellipsis, 18, 19, 20]
end
test "current page at last" do
result = Pagination.page_numbers(page(20, 20))
assert result == [1, :ellipsis, 19, 20]
end
test "8 pages with current at 4" do
result = Pagination.page_numbers(page(4, 8))
assert result == [1, :ellipsis, 3, 4, 5, :ellipsis, 8]
end
end
describe "showing_text/1" do
test "returns showing range" do
assert Pagination.showing_text(page(1, 5, 25, 120)) == "Showing 1\u201325 of 120"
assert Pagination.showing_text(page(2, 5, 25, 120)) == "Showing 26\u201350 of 120"
assert Pagination.showing_text(page(5, 5, 25, 120)) == "Showing 101\u2013120 of 120"
end
test "returns no results when empty" do
assert Pagination.showing_text(page(1, 1, 25, 0)) == "No results"
end
end
describe "parse_page/1" do
test "returns 1 for nil" do
assert Pagination.parse_page(%{}) == 1
end
test "parses valid string" do
assert Pagination.parse_page(%{"page" => "3"}) == 3
end
test "returns 1 for invalid string" do
assert Pagination.parse_page(%{"page" => "abc"}) == 1
assert Pagination.parse_page(%{"page" => "0"}) == 1
assert Pagination.parse_page(%{"page" => "-1"}) == 1
end
test "accepts integer values" do
assert Pagination.parse_page(%{"page" => 5}) == 5
end
test "uses custom key" do
assert Pagination.parse_page(%{"p" => "7"}, "p") == 7
end
end
describe "paginate/2" do
test "paginates a query" do
# Create some subscribers as test data
for i <- 1..7 do
%Berrypod.Newsletter.Subscriber{}
|> Berrypod.Newsletter.Subscriber.changeset(%{
email: "pag#{i}@example.com",
status: "confirmed",
confirmed_at: DateTime.utc_now() |> DateTime.truncate(:second),
consent_text: "test"
})
|> Berrypod.Repo.insert!()
end
import Ecto.Query
query =
from(s in Berrypod.Newsletter.Subscriber,
order_by: [asc: s.email]
)
# Page 1 of 3 (3 per page, 7 total)
result = Pagination.paginate(query, page: 1, per_page: 3)
assert length(result.items) == 3
assert result.page == 1
assert result.per_page == 3
assert result.total_count == 7
assert result.total_pages == 3
# Page 3 has 1 item
result = Pagination.paginate(query, page: 3, per_page: 3)
assert length(result.items) == 1
assert result.page == 3
# Page beyond range is clamped
result = Pagination.paginate(query, page: 99, per_page: 3)
assert result.page == 3
end
test "handles empty result set" do
import Ecto.Query
query =
from(s in Berrypod.Newsletter.Subscriber,
where: s.email == "nonexistent@nope.com"
)
result = Pagination.paginate(query, page: 1, per_page: 25)
assert result.items == []
assert result.total_count == 0
assert result.total_pages == 1
assert result.page == 1
end
end
# Helpers for building test structs
defp page(current, total) do
%Pagination{
items: [],
page: current,
per_page: 25,
total_count: total * 25,
total_pages: total
}
end
defp page(current, total_pages, per_page, total_count) do
%Pagination{
items: [],
page: current,
per_page: per_page,
total_count: total_count,
total_pages: total_pages
}
end
end