Skip to content

Commit

Permalink
fix: Correctly return cursor in list method (#127)
Browse files Browse the repository at this point in the history
* Return hasMore field and null cursor for last page

* Fix tests

* Improve test coverage
  • Loading branch information
harryzcy authored Jul 17, 2022
1 parent 04368dc commit a993ff9
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 42 deletions.
17 changes: 12 additions & 5 deletions internal/email/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type ListResult struct {
Count int `json:"count"`
Items []TimeIndex `json:"items"`
NextCursor *Cursor `json:"nextCursor"`
HasMore bool `json:"hasMore"`
}

// List lists emails in DynamoDB
Expand Down Expand Up @@ -62,18 +63,24 @@ func List(ctx context.Context, api QueryAPI, input ListInput) (*ListResult, erro
return nil, err
}

return &ListResult{
Count: len(result.items),
Items: result.items,
NextCursor: &Cursor{
var nextCursor *Cursor
if result.hasMore {
nextCursor = &Cursor{
QueryInfo: QueryInfo{
Type: input.Type,
Year: input.Year,
Month: input.Month,
Order: input.Order,
},
LastEvaluatedKey: result.lastEvaluatedKey,
},
}
}

return &ListResult{
Count: len(result.items),
Items: result.items,
NextCursor: nextCursor,
HasMore: result.hasMore,
}, nil
}

Expand Down
2 changes: 2 additions & 0 deletions internal/email/list_query.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var unmarshalListOfMaps = attributevalue.UnmarshalListOfMaps
type listQueryResult struct {
items []TimeIndex
lastEvaluatedKey map[string]types.AttributeValue
hasMore bool
}

// listByYearMonth returns a list of emails within a DynamoDB partition.
Expand Down Expand Up @@ -73,5 +74,6 @@ func listByYearMonth(ctx context.Context, api QueryAPI, input listQueryInput) (l
return listQueryResult{
items: items,
lastEvaluatedKey: resp.LastEvaluatedKey,
hasMore: resp.LastEvaluatedKey != nil && len(resp.LastEvaluatedKey) > 0,
}, nil
}
103 changes: 66 additions & 37 deletions internal/email/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package email

import (
"context"
"errors"
"strconv"
"testing"
"time"
Expand Down Expand Up @@ -30,13 +31,25 @@ func TestList(t *testing.T) {
"DateTime": &types.AttributeValueMemberS{Value: "12-01:01:01"},
},
},
LastEvaluatedKey: map[string]types.AttributeValue{
"MessageID": &types.AttributeValueMemberS{Value: "exampleMessageID"},
},
}, nil
})
},
input: ListInput{
Type: "inbox",
Year: "2022",
Month: "03",
Order: "desc",
NextCursor: &Cursor{
QueryInfo: QueryInfo{
Type: "inbox",
Year: "2022",
Month: "03",
Order: "desc",
},
},
},
expected: &ListResult{
Count: 1,
Expand All @@ -54,7 +67,11 @@ func TestList(t *testing.T) {
Month: "03",
Order: "desc",
},
LastEvaluatedKey: map[string]types.AttributeValue{
"MessageID": &types.AttributeValueMemberS{Value: "exampleMessageID"},
},
},
HasMore: true,
},
},
{
Expand All @@ -68,6 +85,9 @@ func TestList(t *testing.T) {
"DateTime": &types.AttributeValueMemberS{Value: "12-01:01:01"},
},
},
LastEvaluatedKey: map[string]types.AttributeValue{
"MessageID": &types.AttributeValueMemberS{Value: "exampleMessageID"},
},
}, nil
})
},
Expand All @@ -91,7 +111,11 @@ func TestList(t *testing.T) {
Month: "03",
Order: "desc",
},
LastEvaluatedKey: map[string]types.AttributeValue{
"MessageID": &types.AttributeValueMemberS{Value: "exampleMessageID"},
},
},
HasMore: true,
},
},
{
Expand All @@ -106,43 +130,48 @@ func TestList(t *testing.T) {
},
expectedErr: ErrInvalidInput,
},
// {
// client: func(t *testing.T) QueryAPI {
// return mockQueryAPI(func(ctx context.Context, params *dynamodb.QueryInput, optFns ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error) {
// assert.Fail(t, "this shouldn't be reached")
// return &dynamodb.QueryOutput{}, nil
// })
// },
// input: ListInput{
// Type: "sent",
// Year: "0",
// },
// expectedErr: ErrInvalidInput,
// },
// {
// client: func(t *testing.T) QueryAPI {
// return mockQueryAPI(func(ctx context.Context, params *dynamodb.QueryInput, optFns ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error) {
// return &dynamodb.QueryOutput{}, errors.New("error")
// })
// },
// input: ListInput{
// Type: "draft",
// Year: "2022",
// Month: "3",
// },
// expectedErr: errors.New("error"),
// },
// {
// input: ListInput{
// Type: "draft",
// NextCursor: &Cursor{
// QueryInfo: QueryInfo{
// Type: "inbox",
// },
// },
// },
// expectedErr: ErrQueryNotMatch,
// },
{
client: func(t *testing.T) QueryAPI {
return mockQueryAPI(func(ctx context.Context, params *dynamodb.QueryInput, optFns ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error) {
assert.Fail(t, "this shouldn't be reached")
return &dynamodb.QueryOutput{}, nil
})
},
input: ListInput{
Type: "sent",
Year: "0",
},
expectedErr: ErrInvalidInput,
},
{
client: func(t *testing.T) QueryAPI {
return mockQueryAPI(func(ctx context.Context, params *dynamodb.QueryInput, optFns ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error) {
return &dynamodb.QueryOutput{}, errors.New("error")
})
},
input: ListInput{
Type: "draft",
Year: "2022",
Month: "3",
},
expectedErr: errors.New("error"),
},
{
client: func(t *testing.T) QueryAPI {
return mockQueryAPI(func(ctx context.Context, params *dynamodb.QueryInput, optFns ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error) {
return &dynamodb.QueryOutput{}, nil
})
},
input: ListInput{
Type: "draft",
NextCursor: &Cursor{
QueryInfo: QueryInfo{
Type: "inbox",
},
},
},
expectedErr: ErrQueryNotMatch,
},
}

for i, test := range tests {
Expand Down

0 comments on commit a993ff9

Please sign in to comment.