Skip to content

Commit 3554221

Browse files
authored
Add ListAll methods to resources with ListWithPagination methods (#282)
* Add ListAll methods to resources with ListWithPagination methods
1 parent 3413314 commit 3554221

14 files changed

+952
-0
lines changed

customer.go

+24
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const (
1818
// See: https://help.shopify.com/api/reference/customer
1919
type CustomerService interface {
2020
List(context.Context, interface{}) ([]Customer, error)
21+
ListAll(context.Context, interface{}) ([]Customer, error)
2122
ListWithPagination(ctx context.Context, options interface{}) ([]Customer, *Pagination, error)
2223
Count(context.Context, interface{}) (int, error)
2324
Get(context.Context, uint64, interface{}) (*Customer, error)
@@ -111,6 +112,29 @@ func (s *CustomerServiceOp) List(ctx context.Context, options interface{}) ([]Cu
111112
return resource.Customers, err
112113
}
113114

115+
// ListAll Lists all customers, iterating over pages
116+
func (s *CustomerServiceOp) ListAll(ctx context.Context, options interface{}) ([]Customer, error) {
117+
collector := []Customer{}
118+
119+
for {
120+
entities, pagination, err := s.ListWithPagination(ctx, options)
121+
122+
if err != nil {
123+
return collector, err
124+
}
125+
126+
collector = append(collector, entities...)
127+
128+
if pagination.NextPageOptions == nil {
129+
break
130+
}
131+
132+
options = pagination.NextPageOptions
133+
}
134+
135+
return collector, nil
136+
}
137+
114138
// ListWithPagination lists customers and return pagination to retrieve next/previous results.
115139
func (s *CustomerServiceOp) ListWithPagination(ctx context.Context, options interface{}) ([]Customer, *Pagination, error) {
116140
path := fmt.Sprintf("%s.json", customersBasePath)

customer_test.go

+112
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,118 @@ func TestCustomerList(t *testing.T) {
3232
}
3333
}
3434

35+
func TestCustomerListAll(t *testing.T) {
36+
setup()
37+
defer teardown()
38+
39+
listURL := fmt.Sprintf("https://fooshop.myshopify.com/%s/customers.json", client.pathPrefix)
40+
41+
cases := []struct {
42+
name string
43+
expectedCustomers []Customer
44+
expectedRequestURLs []string
45+
expectedLinkHeaders []string
46+
expectedBodies []string
47+
expectedErr error
48+
}{
49+
{
50+
name: "Pulls the next page",
51+
expectedRequestURLs: []string{
52+
listURL,
53+
fmt.Sprintf("%s?page_info=pg2", listURL),
54+
},
55+
expectedLinkHeaders: []string{
56+
`<http://valid.url?page_info=pg2>; rel="next"`,
57+
`<http://valid.url?page_info=pg1>; rel="previous"`,
58+
},
59+
expectedBodies: []string{
60+
`{"customers": [{"id":1},{"id":2}]}`,
61+
`{"customers": [{"id":3},{"id":4}]}`,
62+
},
63+
expectedCustomers: []Customer{{Id: 1}, {Id: 2}, {Id: 3}, {Id: 4}},
64+
expectedErr: nil,
65+
},
66+
{
67+
name: "Stops when there is not a next page",
68+
expectedRequestURLs: []string{
69+
listURL,
70+
},
71+
expectedLinkHeaders: []string{
72+
`<http://valid.url?page_info=pg2>; rel="previous"`,
73+
},
74+
expectedBodies: []string{
75+
`{"customers": [{"id":1}]}`,
76+
},
77+
expectedCustomers: []Customer{{Id: 1}},
78+
expectedErr: nil,
79+
},
80+
{
81+
name: "Returns errors when required",
82+
expectedRequestURLs: []string{
83+
listURL,
84+
},
85+
expectedLinkHeaders: []string{
86+
`<http://valid.url?paage_info=pg2>; rel="previous"`,
87+
},
88+
expectedBodies: []string{
89+
`{"customers": []}`,
90+
},
91+
expectedCustomers: []Customer{},
92+
expectedErr: errors.New("page_info is missing"),
93+
},
94+
}
95+
96+
for i, c := range cases {
97+
t.Run(c.name, func(t *testing.T) {
98+
if len(c.expectedRequestURLs) != len(c.expectedLinkHeaders) {
99+
t.Errorf(
100+
"test case must have the same number of expected request urls (%d) as expected link headers (%d)",
101+
len(c.expectedRequestURLs),
102+
len(c.expectedLinkHeaders),
103+
)
104+
105+
return
106+
}
107+
108+
if len(c.expectedRequestURLs) != len(c.expectedBodies) {
109+
t.Errorf(
110+
"test case must have the same number of expected request urls (%d) as expected bodies (%d)",
111+
len(c.expectedRequestURLs),
112+
len(c.expectedBodies),
113+
)
114+
115+
return
116+
}
117+
118+
for i := range c.expectedRequestURLs {
119+
response := &http.Response{
120+
StatusCode: 200,
121+
Body: httpmock.NewRespBodyFromString(c.expectedBodies[i]),
122+
Header: http.Header{
123+
"Link": {c.expectedLinkHeaders[i]},
124+
},
125+
}
126+
127+
httpmock.RegisterResponder("GET", c.expectedRequestURLs[i], httpmock.ResponderFromResponse(response))
128+
}
129+
130+
customers, err := client.Customer.ListAll(context.Background(), nil)
131+
if !reflect.DeepEqual(customers, c.expectedCustomers) {
132+
t.Errorf("test %d Customer.ListAll orders returned %+v, expected %+v", i, customers, c.expectedCustomers)
133+
}
134+
135+
if (c.expectedErr != nil || err != nil) && err.Error() != c.expectedErr.Error() {
136+
t.Errorf(
137+
"test %d Customer.ListAll err returned %+v, expected %+v",
138+
i,
139+
err,
140+
c.expectedErr,
141+
)
142+
}
143+
})
144+
}
145+
}
146+
35147
func TestCustomerListWithPagination(t *testing.T) {
36148
setup()
37149
defer teardown()

order.go

+24
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const (
1919
// See: https://help.shopify.com/api/reference/order
2020
type OrderService interface {
2121
List(context.Context, interface{}) ([]Order, error)
22+
ListAll(context.Context, interface{}) ([]Order, error)
2223
ListWithPagination(context.Context, interface{}) ([]Order, *Pagination, error)
2324
Count(context.Context, interface{}) (int, error)
2425
Get(context.Context, uint64, interface{}) (*Order, error)
@@ -538,6 +539,29 @@ func (s *OrderServiceOp) List(ctx context.Context, options interface{}) ([]Order
538539
return orders, nil
539540
}
540541

542+
// ListAll Lists all orders, iterating over pages
543+
func (s *OrderServiceOp) ListAll(ctx context.Context, options interface{}) ([]Order, error) {
544+
collector := []Order{}
545+
546+
for {
547+
entities, pagination, err := s.ListWithPagination(ctx, options)
548+
549+
if err != nil {
550+
return collector, err
551+
}
552+
553+
collector = append(collector, entities...)
554+
555+
if pagination.NextPageOptions == nil {
556+
break
557+
}
558+
559+
options = pagination.NextPageOptions
560+
}
561+
562+
return collector, nil
563+
}
564+
541565
func (s *OrderServiceOp) ListWithPagination(ctx context.Context, options interface{}) ([]Order, *Pagination, error) {
542566
path := fmt.Sprintf("%s.json", ordersBasePath)
543567
resource := new(OrdersResource)

order_risk.go

+24
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const (
1515
// See: https://shopify.dev/docs/api/admin-rest/2023-10/resources/order-risk
1616
type OrderRiskService interface {
1717
List(context.Context, uint64, interface{}) ([]OrderRisk, error)
18+
ListAll(context.Context, uint64, interface{}) ([]OrderRisk, error)
1819
ListWithPagination(context.Context, uint64, interface{}) ([]OrderRisk, *Pagination, error)
1920
Get(context.Context, uint64, uint64, interface{}) (*OrderRisk, error)
2021
Create(context.Context, uint64, OrderRisk) (*OrderRisk, error)
@@ -79,6 +80,29 @@ func (s *OrderRiskServiceOp) List(ctx context.Context, orderId uint64, options i
7980
return orders, nil
8081
}
8182

83+
// ListAll Lists all OrderRisk, iterating over pages
84+
func (s *OrderRiskServiceOp) ListAll(ctx context.Context, orderId uint64, options interface{}) ([]OrderRisk, error) {
85+
collector := []OrderRisk{}
86+
87+
for {
88+
entities, pagination, err := s.ListWithPagination(ctx, orderId, options)
89+
90+
if err != nil {
91+
return collector, err
92+
}
93+
94+
collector = append(collector, entities...)
95+
96+
if pagination.NextPageOptions == nil {
97+
break
98+
}
99+
100+
options = pagination.NextPageOptions
101+
}
102+
103+
return collector, nil
104+
}
105+
82106
func (s *OrderRiskServiceOp) ListWithPagination(ctx context.Context, orderId uint64, options interface{}) ([]OrderRisk, *Pagination, error) {
83107
path := fmt.Sprintf("%s/%d/%s.json", ordersRiskBasePath, orderId, ordersRiskResourceName)
84108
resource := new(OrdersRisksResource)

order_risk_test.go

+112
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,118 @@ func TestOrderRiskListError(t *testing.T) {
3131
}
3232
}
3333

34+
func TestOrderRiskListAll(t *testing.T) {
35+
setup()
36+
defer teardown()
37+
38+
listURL := fmt.Sprintf("https://fooshop.myshopify.com/%s/orders/450789469/risks.json", client.pathPrefix)
39+
40+
cases := []struct {
41+
name string
42+
expectedOrderRisks []OrderRisk
43+
expectedRequestURLs []string
44+
expectedLinkHeaders []string
45+
expectedBodies []string
46+
expectedErr error
47+
}{
48+
{
49+
name: "Pulls the next page",
50+
expectedRequestURLs: []string{
51+
listURL,
52+
fmt.Sprintf("%s?page_info=pg2", listURL),
53+
},
54+
expectedLinkHeaders: []string{
55+
`<http://valid.url?page_info=pg2>; rel="next"`,
56+
`<http://valid.url?page_info=pg1>; rel="previous"`,
57+
},
58+
expectedBodies: []string{
59+
`{"risks": [{"id":1},{"id":2}]}`,
60+
`{"risks": [{"id":3},{"id":4}]}`,
61+
},
62+
expectedOrderRisks: []OrderRisk{{Id: 1}, {Id: 2}, {Id: 3}, {Id: 4}},
63+
expectedErr: nil,
64+
},
65+
{
66+
name: "Stops when there is not a next page",
67+
expectedRequestURLs: []string{
68+
listURL,
69+
},
70+
expectedLinkHeaders: []string{
71+
`<http://valid.url?page_info=pg2>; rel="previous"`,
72+
},
73+
expectedBodies: []string{
74+
`{"risks": [{"id":1}]}`,
75+
},
76+
expectedOrderRisks: []OrderRisk{{Id: 1}},
77+
expectedErr: nil,
78+
},
79+
{
80+
name: "Returns errors when required",
81+
expectedRequestURLs: []string{
82+
listURL,
83+
},
84+
expectedLinkHeaders: []string{
85+
`<http://valid.url?paage_info=pg2>; rel="previous"`,
86+
},
87+
expectedBodies: []string{
88+
`{"risks": []}`,
89+
},
90+
expectedOrderRisks: []OrderRisk{},
91+
expectedErr: errors.New("page_info is missing"),
92+
},
93+
}
94+
95+
for i, c := range cases {
96+
t.Run(c.name, func(t *testing.T) {
97+
if len(c.expectedRequestURLs) != len(c.expectedLinkHeaders) {
98+
t.Errorf(
99+
"test case must have the same number of expected request urls (%d) as expected link headers (%d)",
100+
len(c.expectedRequestURLs),
101+
len(c.expectedLinkHeaders),
102+
)
103+
104+
return
105+
}
106+
107+
if len(c.expectedRequestURLs) != len(c.expectedBodies) {
108+
t.Errorf(
109+
"test case must have the same number of expected request urls (%d) as expected bodies (%d)",
110+
len(c.expectedRequestURLs),
111+
len(c.expectedBodies),
112+
)
113+
114+
return
115+
}
116+
117+
for i := range c.expectedRequestURLs {
118+
response := &http.Response{
119+
StatusCode: 200,
120+
Body: httpmock.NewRespBodyFromString(c.expectedBodies[i]),
121+
Header: http.Header{
122+
"Link": {c.expectedLinkHeaders[i]},
123+
},
124+
}
125+
126+
httpmock.RegisterResponder("GET", c.expectedRequestURLs[i], httpmock.ResponderFromResponse(response))
127+
}
128+
129+
risks, err := client.OrderRisk.ListAll(context.Background(), 450789469, nil)
130+
if !reflect.DeepEqual(risks, c.expectedOrderRisks) {
131+
t.Errorf("test %d OrderRisk.ListAll orders returned %+v, expected %+v", i, risks, c.expectedOrderRisks)
132+
}
133+
134+
if (c.expectedErr != nil || err != nil) && err.Error() != c.expectedErr.Error() {
135+
t.Errorf(
136+
"test %d OrderRisk.ListAll err returned %+v, expected %+v",
137+
i,
138+
err,
139+
c.expectedErr,
140+
)
141+
}
142+
})
143+
}
144+
}
145+
34146
func TestOrderRiskListWithPagination(t *testing.T) {
35147
setup()
36148
defer teardown()

0 commit comments

Comments
 (0)