178 lines
3.7 KiB
Go
178 lines
3.7 KiB
Go
package pagination
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func init() {
|
|
gin.SetMode(gin.TestMode)
|
|
}
|
|
|
|
func newContext(query string) *gin.Context {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = httptest.NewRequest(http.MethodGet, "/?"+query, nil)
|
|
return c
|
|
}
|
|
|
|
func TestParse_Defaults(t *testing.T) {
|
|
c := newContext("")
|
|
p := Parse(c)
|
|
assert.Equal(t, 1, p.Page)
|
|
assert.Equal(t, DefaultPerPage, p.PerPage)
|
|
assert.Equal(t, 0, p.Offset)
|
|
}
|
|
|
|
func TestParse_ValidParams(t *testing.T) {
|
|
c := newContext("page=3&per_page=10")
|
|
p := Parse(c)
|
|
assert.Equal(t, 3, p.Page)
|
|
assert.Equal(t, 10, p.PerPage)
|
|
assert.Equal(t, 20, p.Offset) // (3-1)*10
|
|
}
|
|
|
|
func TestParse_PageZero(t *testing.T) {
|
|
c := newContext("page=0")
|
|
p := Parse(c)
|
|
assert.Equal(t, 1, p.Page)
|
|
assert.Equal(t, DefaultPerPage, p.PerPage)
|
|
assert.Equal(t, 0, p.Offset)
|
|
}
|
|
|
|
func TestParse_NegativePage(t *testing.T) {
|
|
c := newContext("page=-5")
|
|
p := Parse(c)
|
|
assert.Equal(t, 1, p.Page)
|
|
assert.Equal(t, 0, p.Offset)
|
|
}
|
|
|
|
func TestParse_PerPageZero(t *testing.T) {
|
|
c := newContext("per_page=0")
|
|
p := Parse(c)
|
|
assert.Equal(t, 1, p.Page)
|
|
assert.Equal(t, DefaultPerPage, p.PerPage)
|
|
assert.Equal(t, 0, p.Offset)
|
|
}
|
|
|
|
func TestParse_NegativePerPage(t *testing.T) {
|
|
c := newContext("per_page=-10")
|
|
p := Parse(c)
|
|
assert.Equal(t, DefaultPerPage, p.PerPage)
|
|
}
|
|
|
|
func TestParse_PerPageExceedsMax(t *testing.T) {
|
|
c := newContext("per_page=500")
|
|
p := Parse(c)
|
|
assert.Equal(t, MaxPerPage, p.PerPage)
|
|
}
|
|
|
|
func TestParse_PerPageExactlyMax(t *testing.T) {
|
|
c := newContext("per_page=100")
|
|
p := Parse(c)
|
|
assert.Equal(t, MaxPerPage, p.PerPage)
|
|
}
|
|
|
|
func TestParse_PerPageJustAboveMax(t *testing.T) {
|
|
c := newContext("per_page=101")
|
|
p := Parse(c)
|
|
assert.Equal(t, MaxPerPage, p.PerPage)
|
|
}
|
|
|
|
func TestParse_PerPageJustBelowMax(t *testing.T) {
|
|
c := newContext("per_page=99")
|
|
p := Parse(c)
|
|
assert.Equal(t, 99, p.PerPage)
|
|
}
|
|
|
|
func TestParse_NonNumericPage(t *testing.T) {
|
|
// strconv.Atoi returns 0 for non-numeric, which gets clamped to 1
|
|
c := newContext("page=abc")
|
|
p := Parse(c)
|
|
assert.Equal(t, 1, p.Page)
|
|
}
|
|
|
|
func TestParse_NonNumericPerPage(t *testing.T) {
|
|
c := newContext("per_page=abc")
|
|
p := Parse(c)
|
|
assert.Equal(t, DefaultPerPage, p.PerPage)
|
|
}
|
|
|
|
func TestParse_OffsetCalculation(t *testing.T) {
|
|
tests := []struct {
|
|
page, perPage, expectedOffset int
|
|
}{
|
|
{1, 25, 0},
|
|
{2, 25, 25},
|
|
{3, 10, 20},
|
|
{10, 50, 450},
|
|
{1, 1, 0},
|
|
}
|
|
for _, tt := range tests {
|
|
c := newContext("")
|
|
// Manually set query params
|
|
c.Request.URL.RawQuery = "page=" + itoa(tt.page) + "&per_page=" + itoa(tt.perPage)
|
|
p := Parse(c)
|
|
assert.Equal(t, tt.expectedOffset, p.Offset, "page=%d perPage=%d", tt.page, tt.perPage)
|
|
}
|
|
}
|
|
|
|
func TestOffsetToPage_NormalCases(t *testing.T) {
|
|
tests := []struct {
|
|
offset, perPage, expected int
|
|
}{
|
|
{0, 25, 1},
|
|
{24, 25, 1},
|
|
{25, 25, 2},
|
|
{50, 25, 3},
|
|
{0, 10, 1},
|
|
{9, 10, 1},
|
|
{10, 10, 2},
|
|
{100, 50, 3},
|
|
}
|
|
for _, tt := range tests {
|
|
result := OffsetToPage(tt.offset, tt.perPage)
|
|
assert.Equal(t, tt.expected, result, "offset=%d perPage=%d", tt.offset, tt.perPage)
|
|
}
|
|
}
|
|
|
|
func TestOffsetToPage_ZeroPerPage(t *testing.T) {
|
|
assert.Equal(t, 1, OffsetToPage(100, 0))
|
|
}
|
|
|
|
func TestOffsetToPage_NegativePerPage(t *testing.T) {
|
|
assert.Equal(t, 1, OffsetToPage(100, -5))
|
|
}
|
|
|
|
func TestOffsetToPage_ZeroOffset(t *testing.T) {
|
|
assert.Equal(t, 1, OffsetToPage(0, 25))
|
|
}
|
|
|
|
// itoa is a small helper to avoid importing strconv in test
|
|
func itoa(n int) string {
|
|
if n == 0 {
|
|
return "0"
|
|
}
|
|
neg := false
|
|
if n < 0 {
|
|
neg = true
|
|
n = -n
|
|
}
|
|
var buf [20]byte
|
|
i := len(buf)
|
|
for n > 0 {
|
|
i--
|
|
buf[i] = byte('0' + n%10)
|
|
n /= 10
|
|
}
|
|
if neg {
|
|
i--
|
|
buf[i] = '-'
|
|
}
|
|
return string(buf[i:])
|
|
}
|