refactor: version cursor - don't allow for nullable values

This commit is contained in:
Dawid Wysokiński 2024-02-06 07:49:01 +01:00
parent 74c5d842ce
commit 7f614877c5
Signed by: Kichiyaki
GPG Key ID: B5445E357FB8B892
5 changed files with 34 additions and 71 deletions

View File

@ -50,18 +50,19 @@ func (a listVersionsParamsApplier) apply(q *bun.SelectQuery) *bun.SelectQuery {
} }
for _, s := range a.params.Sort() { for _, s := range a.params.Sort() {
codeCursor := a.params.Cursor().Code() cursorZero := a.params.Cursor().IsZero()
cursorCode := a.params.Cursor().Code()
switch s { switch s {
case domain.VersionSortCodeASC: case domain.VersionSortCodeASC:
if codeCursor.Valid { if !cursorZero {
q = q.Where("version.code >= ?", codeCursor.Value) q = q.Where("version.code >= ?", cursorCode)
} }
q = q.Order("version.code ASC") q = q.Order("version.code ASC")
case domain.VersionSortCodeDESC: case domain.VersionSortCodeDESC:
if codeCursor.Valid { if !cursorZero {
q = q.Where("version.code <= ?", codeCursor.Value) q = q.Where("version.code <= ?", cursorCode)
} }
q = q.Order("version.code DESC") q = q.Order("version.code DESC")

View File

@ -80,10 +80,7 @@ func testVersionRepository(t *testing.T, newRepos func(t *testing.T) repositorie
require.Greater(t, len(res.Versions()), 2) require.Greater(t, len(res.Versions()), 2)
require.NoError(t, params.SetCursor(domaintest.NewVersionCursor(t, func(cfg *domaintest.VersionCursorConfig) { require.NoError(t, params.SetCursor(domaintest.NewVersionCursor(t, func(cfg *domaintest.VersionCursorConfig) {
cfg.Code = domain.NullString{ cfg.Code = res.Versions()[1].Code()
Value: res.Versions()[1].Code(),
Valid: true,
}
}))) })))
return params return params
@ -95,7 +92,7 @@ func testVersionRepository(t *testing.T, newRepos func(t *testing.T) repositorie
return cmp.Compare(a.Code(), b.Code()) return cmp.Compare(a.Code(), b.Code())
})) }))
for _, v := range res.Versions() { for _, v := range res.Versions() {
assert.GreaterOrEqual(t, v.Code(), params.Cursor().Code().Value, v.Code()) assert.GreaterOrEqual(t, v.Code(), params.Cursor().Code(), v.Code())
} }
}, },
assertError: func(t *testing.T, err error) { assertError: func(t *testing.T, err error) {
@ -116,10 +113,7 @@ func testVersionRepository(t *testing.T, newRepos func(t *testing.T) repositorie
require.Greater(t, len(res.Versions()), 2) require.Greater(t, len(res.Versions()), 2)
require.NoError(t, params.SetCursor(domaintest.NewVersionCursor(t, func(cfg *domaintest.VersionCursorConfig) { require.NoError(t, params.SetCursor(domaintest.NewVersionCursor(t, func(cfg *domaintest.VersionCursorConfig) {
cfg.Code = domain.NullString{ cfg.Code = res.Versions()[1].Code()
Value: res.Versions()[1].Code(),
Valid: true,
}
}))) })))
return params return params
@ -131,7 +125,7 @@ func testVersionRepository(t *testing.T, newRepos func(t *testing.T) repositorie
return cmp.Compare(a.Code(), b.Code()) * -1 return cmp.Compare(a.Code(), b.Code()) * -1
})) }))
for _, v := range res.Versions() { for _, v := range res.Versions() {
assert.LessOrEqual(t, v.Code(), params.Cursor().Code().Value, v.Code()) assert.LessOrEqual(t, v.Code(), params.Cursor().Code(), v.Code())
} }
}, },
assertError: func(t *testing.T, err error) { assertError: func(t *testing.T, err error) {

View File

@ -7,17 +7,14 @@ import (
) )
type VersionCursorConfig struct { type VersionCursorConfig struct {
Code domain.NullString Code string
} }
func NewVersionCursor(tb TestingTB, opts ...func(cfg *VersionCursorConfig)) domain.VersionCursor { func NewVersionCursor(tb TestingTB, opts ...func(cfg *VersionCursorConfig)) domain.VersionCursor {
tb.Helper() tb.Helper()
cfg := &VersionCursorConfig{ cfg := &VersionCursorConfig{
Code: domain.NullString{ Code: RandVersionCode(),
Value: RandVersionCode(),
Valid: true,
},
} }
for _, opt := range opts { for _, opt := range opts {

View File

@ -108,17 +108,13 @@ const (
) )
type VersionCursor struct { type VersionCursor struct {
code NullString code string
} }
const versionCursorModelName = "VersionCursor" const versionCursorModelName = "VersionCursor"
func NewVersionCursor(code NullString) (VersionCursor, error) { func NewVersionCursor(code string) (VersionCursor, error) {
if !code.Valid { if err := validateVersionCode(code); err != nil {
return VersionCursor{}, nil
}
if err := validateVersionCode(code.Value); err != nil {
return VersionCursor{}, ValidationError{ return VersionCursor{}, ValidationError{
Model: versionCursorModelName, Model: versionCursorModelName,
Field: "code", Field: "code",
@ -152,10 +148,7 @@ func decodeVersionCursor(encoded string) (VersionCursor, error) {
return VersionCursor{}, ErrInvalidCursor return VersionCursor{}, ErrInvalidCursor
} }
vc, err := NewVersionCursor(NullString{ vc, err := NewVersionCursor(code)
Value: code,
Valid: true,
})
if err != nil { if err != nil {
return VersionCursor{}, ErrInvalidCursor return VersionCursor{}, ErrInvalidCursor
} }
@ -163,12 +156,12 @@ func decodeVersionCursor(encoded string) (VersionCursor, error) {
return vc, nil return vc, nil
} }
func (vc VersionCursor) Code() NullString { func (vc VersionCursor) Code() string {
return vc.code return vc.code
} }
func (vc VersionCursor) IsZero() bool { func (vc VersionCursor) IsZero() bool {
return !vc.code.Valid return vc == VersionCursor{}
} }
func (vc VersionCursor) Encode() string { func (vc VersionCursor) Encode() string {
@ -176,7 +169,7 @@ func (vc VersionCursor) Encode() string {
return "" return ""
} }
return base64.StdEncoding.EncodeToString([]byte("code=" + vc.code.Value)) return base64.StdEncoding.EncodeToString([]byte("code=" + vc.code))
} }
type ListVersionsParams struct { type ListVersionsParams struct {
@ -287,10 +280,7 @@ func NewListVersionsResult(versions Versions, next Version) (ListVersionsResult,
} }
if len(versions) > 0 { if len(versions) > 0 {
res.self, err = NewVersionCursor(NullString{ res.self, err = NewVersionCursor(versions[0].Code())
Value: versions[0].Code(),
Valid: true,
})
if err != nil { if err != nil {
return ListVersionsResult{}, ValidationError{ return ListVersionsResult{}, ValidationError{
Model: listVersionsResultModelName, Model: listVersionsResultModelName,
@ -300,15 +290,14 @@ func NewListVersionsResult(versions Versions, next Version) (ListVersionsResult,
} }
} }
res.next, err = NewVersionCursor(NullString{ if !next.IsZero() {
Value: next.Code(), res.next, err = NewVersionCursor(next.Code())
Valid: !next.IsZero(), if err != nil {
}) return ListVersionsResult{}, ValidationError{
if err != nil { Model: listVersionsResultModelName,
return ListVersionsResult{}, ValidationError{ Field: "next",
Model: listVersionsResultModelName, Err: err,
Field: "next", }
Err: err,
} }
} }

View File

@ -17,7 +17,7 @@ func TestNewVersionCursor(t *testing.T) {
validVersionCursor := domaintest.NewVersionCursor(t) validVersionCursor := domaintest.NewVersionCursor(t)
type args struct { type args struct {
code domain.NullString code string
} }
type test struct { type test struct {
@ -34,23 +34,13 @@ func TestNewVersionCursor(t *testing.T) {
}, },
expectedErr: nil, expectedErr: nil,
}, },
{
name: "OK: nil code",
args: args{
code: domain.NullString{},
},
expectedErr: nil,
},
} }
for _, versionCodeTest := range newVersionCodeValidationTests() { for _, versionCodeTest := range newVersionCodeValidationTests() {
tests = append(tests, test{ tests = append(tests, test{
name: versionCodeTest.name, name: versionCodeTest.name,
args: args{ args: args{
code: domain.NullString{ code: versionCodeTest.code,
Value: versionCodeTest.code,
Valid: true,
},
}, },
expectedErr: domain.ValidationError{ expectedErr: domain.ValidationError{
Model: "VersionCursor", Model: "VersionCursor",
@ -72,11 +62,7 @@ func TestNewVersionCursor(t *testing.T) {
return return
} }
assert.Equal(t, tt.args.code, vc.Code()) assert.Equal(t, tt.args.code, vc.Code())
if tt.args.code.Valid { assert.NotEmpty(t, vc.Encode())
assert.NotEmpty(t, vc.Encode())
} else {
assert.Empty(t, vc.Encode())
}
}) })
} }
} }
@ -231,7 +217,6 @@ func TestListVersionsParams_SetEncodedCursor(t *testing.T) {
fmt.Println(tt.expectedErr.Error()) fmt.Println(tt.expectedErr.Error())
return return
} }
assert.True(t, params.Cursor().Code().Valid)
assert.Equal(t, tt.expectedCursor.Code(), params.Cursor().Code()) assert.Equal(t, tt.expectedCursor.Code(), params.Cursor().Code())
assert.Equal(t, tt.args.cursor, params.Cursor().Encode()) assert.Equal(t, tt.args.cursor, params.Cursor().Encode())
}) })
@ -319,10 +304,8 @@ func TestNewListVersionsResult(t *testing.T) {
res, err := domain.NewListVersionsResult(versions, next) res, err := domain.NewListVersionsResult(versions, next)
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, versions, res.Versions()) assert.Equal(t, versions, res.Versions())
assert.True(t, res.Self().Code().Valid) assert.Equal(t, versions[0].Code(), res.Self().Code())
assert.Equal(t, versions[0].Code(), res.Self().Code().Value) assert.Equal(t, next.Code(), res.Next().Code())
assert.True(t, res.Next().Code().Valid)
assert.Equal(t, next.Code(), res.Next().Code().Value)
}) })
t.Run("OK: without next", func(t *testing.T) { t.Run("OK: without next", func(t *testing.T) {
@ -331,8 +314,7 @@ func TestNewListVersionsResult(t *testing.T) {
res, err := domain.NewListVersionsResult(versions, domain.Version{}) res, err := domain.NewListVersionsResult(versions, domain.Version{})
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, versions, res.Versions()) assert.Equal(t, versions, res.Versions())
assert.True(t, res.Self().Code().Valid) assert.Equal(t, versions[0].Code(), res.Self().Code())
assert.Equal(t, versions[0].Code(), res.Self().Code().Value)
assert.True(t, res.Next().IsZero()) assert.True(t, res.Next().IsZero())
}) })