import files, add README & LICENSE
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
package cursor
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"testing"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
"github.com/go-jet/jet/v2/mysql"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestValueMethods(t *testing.T) {
|
||||
RegisterColumn(Scratch.ID)
|
||||
|
||||
intVal, err := NewInt64Value(7, Scratch.ID).Value()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(7), intVal)
|
||||
|
||||
uintVal, err := NewUint64Value(9, Spare.ID).Value()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint64(9), uintVal)
|
||||
}
|
||||
|
||||
func TestCursorString(t *testing.T) {
|
||||
RegisterColumn(User.ID)
|
||||
|
||||
c := NewCursor(NewInt64Value(3, User.ID), User.ID, OrderAscending)
|
||||
assert.JSONEq(t, `{"index":{"key":{"table":"user","column":"id"},"val":3},"order_col":{"table":"user","column":"id"},"order_dir":"ASC"}`, c.String())
|
||||
}
|
||||
|
||||
func TestUsesTupleOrderingEdgeCases(t *testing.T) {
|
||||
assert.False(t, (*Cursor[mysql.IntegerExpression, mysql.ColumnInteger])(nil).UsesTupleOrdering())
|
||||
|
||||
RegisterColumn(User.ID)
|
||||
sameCol := NewCursor(NewInt64Value(0, User.ID), User.ID, OrderDescending)
|
||||
assert.False(t, sameCol.UsesTupleOrdering())
|
||||
}
|
||||
|
||||
func TestPaginateWrapperFuncs(t *testing.T) {
|
||||
RegisterColumn(User.ID, Meeting.StartTime)
|
||||
|
||||
intCursor := NewCursor(NewInt64Value(1, User.ID), User.ID, OrderDescending)
|
||||
sql := User.SELECT(User.AllColumns).WHERE(PaginateIntConds(intCursor)).DebugSql()
|
||||
assert.Contains(t, sql, "user.id < 1")
|
||||
|
||||
strCursor := NewCursor(NewStringValue("x", MeetingRoom.ID), MeetingRoom.ID, OrderDescending)
|
||||
RegisterColumn(MeetingRoom.ID)
|
||||
sql = MeetingRoom.SELECT(MeetingRoom.AllColumns).WHERE(PaginateUUIDConds(strCursor)).DebugSql()
|
||||
assert.Contains(t, sql, "meeting_room.id < 'x'")
|
||||
|
||||
tsCursor := NewCursor(
|
||||
NewTimestampValue(mustTime("2026-01-01T00:00:00Z"), Meeting.StartTime),
|
||||
Meeting.StartTime,
|
||||
OrderDescending,
|
||||
)
|
||||
sql = Meeting.SELECT(Meeting.AllColumns).WHERE(PaginateTimestampConds(tsCursor)).DebugSql()
|
||||
assert.Contains(t, sql, "meeting.start_time <")
|
||||
}
|
||||
|
||||
func TestNewCursorFromJSONError(t *testing.T) {
|
||||
RegisterColumn(User.ID)
|
||||
_, err := NewCursorFromJSON(NewInt64Value(0, User.ID), []byte(`{invalid`))
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestColWrongTypePanics(t *testing.T) {
|
||||
RegisterColumn(User.ID)
|
||||
|
||||
// Key points at user.id (integer) but we construct StringValue for it.
|
||||
sv := &StringValue{Key: NewColumnKey(User.ID), Val: "x"}
|
||||
assert.Panics(t, func() { sv.Col() })
|
||||
}
|
||||
|
||||
func TestQueryCount(t *testing.T) {
|
||||
registerMeetingCursorColumns(t)
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { db.Close() })
|
||||
|
||||
rows := sqlmock.NewRows([]string{
|
||||
"QueryCountResult.Total",
|
||||
"QueryCountResult.Before",
|
||||
"QueryCountResult.After",
|
||||
}).AddRow(10, 3, 5)
|
||||
mock.ExpectQuery("SELECT").WillReturnRows(rows)
|
||||
|
||||
when := mustTime("2026-06-01T09:00:00Z")
|
||||
start := NewCursor(
|
||||
NewStringValue("", Meeting.ID),
|
||||
Meeting.StartTime,
|
||||
OrderDescending,
|
||||
).CopyWithVals(
|
||||
NewStringValue("meeting-uuid-1", Meeting.ID),
|
||||
NewTimestampValue(when, Meeting.StartTime),
|
||||
)
|
||||
end := start.CopyWithVals(
|
||||
NewStringValue("meeting-uuid-2", Meeting.ID),
|
||||
NewTimestampValue(when, Meeting.StartTime),
|
||||
)
|
||||
|
||||
sqlo := &queryableDB{db: db}
|
||||
res, err := QueryCount(sqlo, Meeting.ID, Meeting, mysql.Bool(true), start, end)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, QueryCountResult{Total: 10, Before: 3, After: 5}, res)
|
||||
require.NoError(t, mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
func TestQueryCountError(t *testing.T) {
|
||||
registerMeetingCursorColumns(t)
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { db.Close() })
|
||||
|
||||
mock.ExpectQuery("SELECT").WillReturnError(assert.AnError)
|
||||
|
||||
when := mustTime("2026-06-01T09:00:00Z")
|
||||
cursor := NewCursor(
|
||||
NewStringValue("", Meeting.ID),
|
||||
Meeting.StartTime,
|
||||
OrderDescending,
|
||||
).CopyWithVals(
|
||||
NewStringValue("meeting-uuid-1", Meeting.ID),
|
||||
NewTimestampValue(when, Meeting.StartTime),
|
||||
)
|
||||
|
||||
sqlo := &queryableDB{db: db}
|
||||
_, err = QueryCount(sqlo, Meeting.ID, Meeting, mysql.Bool(true), cursor, cursor)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "failed to query count")
|
||||
}
|
||||
|
||||
func TestBuildQueryCountFnInvoke(t *testing.T) {
|
||||
registerMeetingCursorColumns(t)
|
||||
|
||||
db, mock, err := sqlmock.New()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { db.Close() })
|
||||
|
||||
rows := sqlmock.NewRows([]string{
|
||||
"QueryCountResult.Total",
|
||||
"QueryCountResult.Before",
|
||||
"QueryCountResult.After",
|
||||
}).AddRow(1, 0, 0)
|
||||
mock.ExpectQuery("SELECT").WillReturnRows(rows)
|
||||
|
||||
when := mustTime("2026-06-01T09:00:00Z")
|
||||
cursor := NewCursor(
|
||||
NewStringValue("", Meeting.ID),
|
||||
Meeting.StartTime,
|
||||
OrderDescending,
|
||||
).CopyWithVals(
|
||||
NewStringValue("meeting-uuid-1", Meeting.ID),
|
||||
NewTimestampValue(when, Meeting.StartTime),
|
||||
)
|
||||
|
||||
fn := BuildQueryCountFn(Meeting.ID, Meeting, mysql.Bool(true))
|
||||
res, err := fn(&queryableDB{db: db}, cursor, cursor)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, res.Total)
|
||||
}
|
||||
|
||||
// queryableDB implements dbx.Queryable for tests.
|
||||
type queryableDB struct {
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func (q *queryableDB) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
|
||||
return q.db.QueryContext(ctx, query, args...)
|
||||
}
|
||||
|
||||
func (q *queryableDB) Query(query string, args ...any) (*sql.Rows, error) {
|
||||
return q.db.Query(query, args...)
|
||||
}
|
||||
Reference in New Issue
Block a user