Files
past-go/past-go/internal/handler/list_pagination_test.go
T
Blizzard 4934a69581 feat: migrate to PostgreSQL GORM and MinIO file storage
Use UUID models and soft deletion, persist file relationships with deduplicated monthly MinIO objects, and add admin file management. Update mini-program media handling and add local dev configuration.
2026-11-01 11:48:45 +08:00

72 lines
3.2 KiB
Go

package handler
import (
"database/sql/driver"
"encoding/json"
"past/internal/httpapi"
"past/internal/testdb"
"strings"
"testing"
)
func TestPagedListsBoundQueriesAndKeepMemberScope(t *testing.T) {
for _, tt := range []struct {
name, uri, table string
handler httpapi.HandlerFunc
args []any
extra []testdb.Step
}{
{"songs", "/api/songsList", "songs", songsList, []any{int64(1), int64(3), int64(20), int64(20)}, nil},
{"albums", "/api/albumList", "albums", albumList, []any{int64(1), int64(3), int64(20), int64(20)}, []testdb.Step{{Match: "FROM photos p JOIN albums a", Columns: []string{"c"}, Rows: [][]driver.Value{{int64(83)}}}}},
{"photos", "/api/photos?album_id=9", "photos", photos, []any{int64(1), int64(3), "9", int64(20), int64(20)}, nil},
{"timeline", "/api/timelineList", "timeline", timelineList, []any{int64(1), int64(3), int64(20), int64(20)}, []testdb.Step{{Match: "event_date >= TO_CHAR(CURRENT_DATE,'YYYY-MM-DD')", Columns: []string{"id", "event_date"}, Rows: [][]driver.Value{{int64(50), "2026-12-01"}}}}},
{"checkins", "/api/checkinList", "checkins", checkinList, []any{int64(1), int64(3), int64(20), int64(20)}, []testdb.Step{{Match: "FROM checkin_logs WHERE couple_id = ?", Args: []any{int64(22)}, Columns: []string{"c"}, Rows: [][]driver.Value{{int64(90)}}}}},
{"comments", "/api/diaryCommentList?diary_id=9", "diary_comments", diaryCommentList, []any{int64(9), int64(1), int64(3), int64(20), int64(20)}, nil},
} {
t.Run(tt.name, func(t *testing.T) {
uri := tt.uri
if strings.Contains(uri, "?") {
uri += "&"
} else {
uri += "?"
}
uri += "page=2&page_size=20"
steps := []testdb.Step{uidStep(1), cidStep(22), {Match: "SELECT user1_id, user2_id FROM couples", Columns: []string{"user1_id", "user2_id"}, Rows: [][]driver.Value{{int64(1), int64(3)}}},
{Match: "LIMIT ? OFFSET ?", Args: tt.args, Check: func(q string, _ []any) error {
if !strings.Contains(q, "IN (?, ?)") {
t.Errorf("missing member predicate: %s", q)
}
return nil
}, Columns: []string{"id"}, Rows: [][]driver.Value{{int64(21)}}},
{Match: "SELECT COUNT(*) as c FROM " + tt.table, Columns: []string{"c"}, Rows: [][]driver.Value{{int64(41)}}}}
steps = append(steps, tt.extra...)
c, out, _ := permissionCtx(t, "GET", uri, "", steps)
tt.handler(c)
if out.Code != 200 {
t.Fatalf("status %d: %s", out.Code, out.Body.String())
}
var result map[string]any
if err := json.Unmarshal(out.Body.Bytes(), &result); err != nil {
t.Fatal(err)
}
if result["total"] != float64(41) || result["page"] != float64(2) || result["has_more"] != true {
t.Fatalf("wrong pagination: %s", out.Body.String())
}
if len(result["items"].([]any)) != 1 {
t.Fatal("wrong items")
}
if tt.name == "albums" && result["photo_total"] != float64(83) {
t.Fatal("photo total must cover all albums")
}
})
}
}
func TestListPaginationCapsPageSizeAndClampsPage(t *testing.T) {
c, _, _ := permissionCtx(t, "GET", "/api/list?page=-1&page_size=9999", "", nil)
suffix, args := listWindow(c)
if suffix != " LIMIT ? OFFSET ?" || args[0] != int64(100) || args[1] != int64(0) {
t.Fatalf("unsafe window %s %v", suffix, args)
}
}