Skip to content

Commit

Permalink
fix: pagination via ForEach does not progress past first page (#1)
Browse files Browse the repository at this point in the history
Pagination was never progressing past the first page because the
itemsSeen was being set to the TotalCount, meaning that the loop would
always exit after the first page.

I've added some tests to cover this.

Signed-off-by: Rob Best <[email protected]>
  • Loading branch information
ribbybibby authored Feb 6, 2023
1 parent 91a1458 commit e451b5e
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 1 deletion.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jarcoal/httpmock v1.2.0 h1:gSvTxxFR/MEMfsGrvRbdfpRUMBStovlSRLw0Ep1bwwc=
Expand Down
2 changes: 1 addition & 1 deletion util.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func ForEach[T any](pageFetchFunc func(po PageOptions) (Page[T], error), handler
}
}

itemsSeen += page.TotalCount
itemsSeen += len(page.Items)
if len(page.Items) == 0 || itemsSeen >= page.TotalCount {
break
}
Expand Down
105 changes: 105 additions & 0 deletions util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package dtrack

import (
"errors"
"testing"

"github.com/google/go-cmp/cmp"
)

func TestFetchAll(t *testing.T) {
var wantItems []int
for i := 0; i < 468; i++ {
wantItems = append(wantItems, i)
}
gotItems, err := FetchAll(func(po PageOptions) (p Page[int], err error) {
for i := 0; i < po.PageSize; i++ {
idx := (po.PageSize * (po.PageNumber - 1)) + i
if idx >= len(wantItems) {
break
}
p.Items = append(p.Items, wantItems[idx])
}
p.TotalCount = len(wantItems)
return p, nil
})
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if diff := cmp.Diff(wantItems, gotItems); diff != "" {
t.Errorf("unexpected items:\n%s", diff)
}
}

func TestFetchAll_PageFetchFuncErr(t *testing.T) {
var testErr = errors.New("test error")
if _, err := FetchAll(
func(po PageOptions) (p Page[int], err error) {
return p, testErr
},
); !errors.Is(err, testErr) {
t.Errorf("expected err but got nil")
}
}

func TestForEach(t *testing.T) {
var (
wantItems []int
gotItems []int
)
for i := 0; i < 468; i++ {
wantItems = append(wantItems, i)
}
if err := ForEach(
func(po PageOptions) (p Page[int], err error) {
for i := 0; i < po.PageSize; i++ {
idx := (po.PageSize * (po.PageNumber - 1)) + i
if idx >= len(wantItems) {
break
}
p.Items = append(p.Items, wantItems[idx])
}
p.TotalCount = len(wantItems)
return p, nil
},
func(item int) error {
gotItems = append(gotItems, item)
return nil
},
); err != nil {
t.Errorf("unexpected error calling ForEach: %s", err)
}
if diff := cmp.Diff(wantItems, gotItems); diff != "" {
t.Errorf("unexpected items:\n%s", diff)
}
}

func TestForEach_PageFetchFuncErr(t *testing.T) {
var testErr = errors.New("test error")
if err := ForEach(
func(po PageOptions) (p Page[int], err error) {
return p, testErr
},
func(item int) error {
return nil
},
); !errors.Is(err, testErr) {
t.Errorf("expected error from pageFetchFunc but got nil")
}
}

func TestForEach_HandlerFuncErr(t *testing.T) {
var testErr = errors.New("test error")
if err := ForEach(
func(po PageOptions) (p Page[int], err error) {
p.Items = []int{0, 1, 2, 3}
p.TotalCount = len(p.Items)
return p, nil
},
func(item int) error {
return testErr
},
); !errors.Is(err, testErr) {
t.Errorf("expected error from handlerFunc but got nil")
}
}

0 comments on commit e451b5e

Please sign in to comment.